事件冒泡、事件捕获、事件委托初探

场景:1

 1 <div class="div1">
 2     click me div1
 3     <div class="div2">click me div2</div>
 4 </div>
 5 
 6 $(".div2").on('click',function(){
 7     alert($(this).attr('class'))
 8 })
 9 
10 $(".div1").on('click',function(){
11    alert($(this).attr('class'))
12 })
View Code

问题1.如果点击click me div2 会显示什么?

a) div2  

b) div1  

c) 先div1 后div2

d) 先div2 后div1

试试jsfiddle

 

如果用文字来描述这个问题大概的意思是“如果一个元素和它的父元素或者祖先元素绑定了相同的事件,哪一个事件处理函数会先执行?” 答案是根据浏览器。没错。在IE下会优先执行div2,在Netscape下会先执行div1。而在Mozilla、opera7下结合了前两者。

为什么不同浏览器之间会有这种差异?

 

IE认为如果点击div2,当然要先触发绑定在div2上事件处理函数,之后再将点击事件向上传递触发绑定在div1上的事件处理函数。

事件冒泡过程:

               / \
---------------| |-----------------
| div1         | |                |
|   -----------| |-----------     |
|   |div2      | |          |     |
|   -------------------------     |
|        事件冒泡                  |
-----------------------------------


Netcape认为因为div2在div1的内部,点击div2后,点击事件应该从div1传递,先触发div1上的事件处理函数,随后点击事件传递到div2上的事件处理函数。

事件捕获过程:

               | |
---------------| |-----------------
| div1         | |                |
|   -----------| |-----------     |
|   |div2      \ /          |     |
|   -------------------------     |
|        事件捕获                   |
-----------------------------------

 

 

 针对这两种情况,W3C在定义dom 事件模型的时候,采取了一个折中的方法。在W3C事件模型中,事件的传播顺序应该从事件捕获阶段为始到事件冒泡阶段结束为终。

                 | |  / \
-----------------| |--| |-----------------
| div1           | |  | |                |
|   -------------| |--| |-----------     |
|   |div2        \ /  | |          |     |
|   --------------------------------     |
|        W3C 事件模型                      |
------------------------------------------

那么问题来了,作为开发人员如何在这种相对比较复杂的环境下来限制事件的传播顺序,从而实现事件绑定的预期效果。

原生js实现方式

element.addEventListener("事件类型",“事件处理函数”,“事件顺序”)

事件顺序=true

事件处理函数在捕获阶段执行

事件顺序 =false

事件处理函数在冒泡阶段执行

 

事件委托

什么是事件委托?利用事件冒泡或者事件捕获原理,如果点击div1,div1自身不处理事件,而是将处理任务委托给父级元素或者祖先元素甚至根节点元素来处理。

 运行:https://jsfiddle.net/Mr_do/22wtxxj5/7/

 1 <div id="divItem">
 2 
 3     <div class="div1">
 4         div1
 5     </div>
 6     
 7     <div class="div2">
 8         div2
 9     </div>
10     
11     <div class="div3">
12         div3
13     </div>
14     
15 </div>
16 
17 
18 
19 $("#divItem").delegate('div','click',function(e){
20     alert($(this).attr('class'))
21 })

 

事件委托好处在于:

1.对于多个相同的事件,可以将任务委托给同一个函数来处理。

2.提高的web应用的性能,减少占用内存

3.结藕js和dom结构的关联,改变dom结构无需改变js处理函数

 

参考内容

事件执行顺序 :http://www.quirksmode.org/js/events_order.html

事件注册原理:http://www.quirksmode.org/js/events_advanced.html

W3C DOM Object Model :https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/

事件冒泡与事件捕获的区别:http://stackoverflow.com/questions/4616694/what-is-event-bubbling-and-capturing

事件冒泡与捕获详解:http://javascript.info/tutorial/bubbling-and-capturing

addEventListener()

DOM Object Model Event :https://www.w3.org/TR/DOM-Level-2-Events/events.html

DOM 事件架构 :http://www.ituring.com.cn/article/428

DOM 事件模型 :http://www.ituring.com.cn/article/420

Jquery 优化事件委托 :http://www.ituring.com.cn/article/467

posted @ 2016-04-10 15:07  Mrdo  阅读(474)  评论(0编辑  收藏  举报