5-11 委托设计
本节编程练习不计算学习进度,请电脑登录imooc.com操作

委托设计

jQuery对事件体系的修正不止是做了属性兼容,重写了事件的方法,还增加状态机,那么这样的处理有什么作用?

事件的核心的处理来了,实现委托

var aaron = $("#aaron")
//同一个元素上绑定不同的事件委托
aaron.on('mousedown','p',function(e){
    alert('委托到p触发')
  e.stopPropagation()
})
aaron.on('mousedown','ul',function(e){
    alert('被阻止了')
})

我们分析这个结构:

  1. 同一个元素上绑定同一个事件,实现不同的委托
  2. 事件绑定在同一个 id 为 aaron 的元素上
  3. 同元素同事件分别绑定,但是同时又都支持冒泡
  4. 同元素上的多个委托可以通过 stopPropagation 控制

 

委托设计的问题

  1. 如何把回调句柄定位到当前的委托元素上面,如果有多个元素上绑定事件回调要如何处理?
  2. 这种结构就涉及了一个事件的先后顺序问题与事件的执行问题,如果回调中设置了stopPropagation 那么冒泡的当然会要被打断了。

在通过 jQuery.event.add 方法的时候我们就知道,数据是被存储在数据缓存 elemData 中,这样我们不需要针对同一个元素上的每个事件都绑定 addEventListener,只需要把数据给分割好放到缓存中,所以同一个元素,不同事件,不重复绑定。  

events = elemData.events = {};
eventHandle = elemData.handle = function(e) {};

数据都储存在 elemData 的缓存里面,除此之外还有一个关键的处理如果 on 中传入参数 selector ,意味着就是有委托的处理,那么我们就需要用一个标记来记录下这个元素到底委托了多少次。

handlers.delegateCount++

可以看出就会自增,用来标记这个元素上有多少个委托的处理,用于后面的处理。

要实现委托,根据冒泡的原理,我们是不是应该把每一个节点层次的事件给规划出来,每个层次的依赖关系?

所以 jQuery 引入了 jQuery.event.handlers 用来区分普通事件与委托事件,形成一个有队列关系的组装事件处理包{elem, handlerObjs}的队列。
在最开始引入 add 方法中增加 delegateCount 用来记录是否委托数,通过传入的 selector 判断,此刻就能派上用场了。
先判断下是否要处理委托,找到委托的句柄。根据之前的测试 demo,在元素 DIV 下面嵌套了 P,然后 P 内嵌套了 A。


 

我们在触发事件的时候,就会在事件缓存中取出这个元素所有对应的事件数据,然后就会分析这个数据的结构,是否有多个监听,是否有委托关系


从图我们可以得出:

  1. 元素本身有事件
  2. 元素又要处理委托事件

那么事件的执行就需要有个先后,jQuery要如何排序呢?

依赖委托节点在 DOM 树的深度安排优先级,委托的 DOM 节点层次越深,其执行优先级越高,委托的事件处理程序相对于直接绑定的事件处理程序在队列的更前面,委托层次越深,该事件处理程序则越靠前。

 

任务

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <script src="http://www.imooc.com/static/lib/jquery/1.9.1/jquery.js" type="text/javascript"></script>
  6. <title>委托设计</title>
  7. </head>
  8. <body>
  9.  
  10.  
  11. <div id="aaron">
  12. <div id='test'>
  13. <ul>
  14. <p>点击测试委托顺序</p>
  15. </ul>
  16. </div>
  17. </div>
  18.  
  19. <ul></ul>
  20.  
  21. <script type="text/javascript">
  22.  
  23. var ul = $('ul')
  24. function show(data){
  25. ul.append('<li>'+ data +'</li>')
  26. }
  27.  
  28. var aaron = $("#aaron")
  29. //同一个元素上绑定不同的事件委托
  30. aaron.on('mousedown','p',function(e){
  31. show('委托到p触发')
  32. // e.stopPropagation()
  33. })
  34. aaron.on('mousedown','ul',function(e){
  35. show('被阻止了')
  36. })
  37.  
  38. aaron.on('mousedown',function(e){
  39. show('mousedown')
  40. })
  41.  
  42.  
  43. $("#test").on('mousedown',function(){
  44. show('test')
  45. })
  46.  
  47. $("body").on('mousedown',function(){
  48. show('body')
  49. })
  50.  
  51.  
  52.  
  53.  
  54. </script>
  55.  
  56. </body>
  57. </html>
下一节