W3C对DOM定义了3个阶段:捕获阶段、目标阶段和冒泡阶段。

当事件被触发时,事件从DOM最外层的元素(在DOM树型结构最顶端的元素)开始,然后沿着最短的路径向target(目标节点)遍历,这就是捕获阶段。

当到达目标节点后,事件就转到目标节点阶段。然后沿着DOM树上溯到最外层的节点,这个过程就是冒泡。

使用如下代码来检测这三个阶段:

 1 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 2 <body style="margin: 0; padding: 0; text-align: center;">
 3     <div id="divParent" style="width: 200px; height: 100px; background-color: #99FF33; margin: 8px auto;">
 4         <div id="divChildA" style="width: 50px; height: 50px; background-color: #00CCCC; margin: 8px; float: left;">A</div>
 5         <div id="divChildB" style="width: 50px; height: 50px; background-color: #CCCC00; margin: 8px; float: left;">B</div>
 6         <div id="divChildC" style="width: 50px; height: 50px; background-color: #FFCC33; margin: 8px; float: left;">C</div>
 7         Parent
 8     </div>
 9     <div id="showResult" style="width: 700px; text-align: left;"></div>
10     <script type="text/javascript">
11         //获取div元素的引用
12         var oBody = document.body,
13             divParent = document.getElementById('divParent'),
14             divA = document.getElementById('divChildA'),
15             divB = document.getElementById('divChildB'),
16             divC = document.getElementById('divChildC'),
17             divResult = document.getElementById('showResult');
18         //检测事件所处阶段
19         function checkPhase(evt) {
20             var phase;
21             //使用eventPhase属性可以获取事件所处阶段的信息
22             //低版本IE没有定义该属性
23             if(evt.eventPhase === 1) {
24                 phase = '捕获阶段';
25             } else if(evt.eventPhase === 2) {
26                 phase = '目标阶段';
27             } else if(evt.eventPhase === 3) {
28                 phase = '冒泡阶段';
29             }
30             return phase;
31         };
32 
33         var oBodyClick = function(evt) {
34             divResult.innerHTML += '[body]=' + checkPhase(evt) + '<br/>';
35             divResult.innerHTML += '[event.currentTarget]=' + evt.currentTarget.id + '<br/>';
36             divResult.innerHTML += '[event.target]=' + evt.target.id + '<br/>';
37             divResult.innerHTML += '-----------------------------------------------<br/>'
38         };
39 
40         var divParentClick = function(evt) {
41             divResult.innerHTML += '[divParent]=' + checkPhase(evt) + '<br/>';
42             divResult.innerHTML += '[event.currentTarget]=' + evt.currentTarget.id + '<br/>';
43             divResult.innerHTML += '[event.target]=' + evt.target.id + '<br/>';
44             divResult.innerHTML += '-----------------------------------------------<br/>'
45         }
46 
47         var divAClick = function(evt) {
48             divResult.innerHTML += '[divA]=' + checkPhase(evt) + '<br/>';
49             divResult.innerHTML += '[event.currentTarget]=' + evt.currentTarget.id + '<br/>';
50             divResult.innerHTML += '[event.target]=' + evt.target.id + '<br/>';
51             divResult.innerHTML += '-----------------------------------------------<br/>'
52         }
53 
54         var divBClick = function(evt) {
55             divResult.innerHTML += '[divB]=' + checkPhase(evt) + '<br/>';
56             divResult.innerHTML += '[event.currentTarget]=' + evt.currentTarget.id + '<br/>';
57             divResult.innerHTML += '[event.target]=' + evt.target.id + '<br/>';
58             divResult.innerHTML += '-----------------------------------------------<br/>'
59         }
60 
61         var divCClick = function(evt) {
62             divResult.innerHTML += '[divC]=' + checkPhase(evt) + '<br/>';
63             divResult.innerHTML += '[event.currentTarget]=' + evt.currentTarget.id + '<br/>';
64             divResult.innerHTML += '[event.target]=' + evt.target.id + '<br/>';
65             divResult.innerHTML += '-----------------------------------------------<br/>'
66         }
67 
68         //addEventListener的第三个参数为false,表示允许冒泡,为true表示禁止冒泡
69         divA.addEventListener('click', divAClick, true);
70         //window.event.stopPropagation(); //取消冒泡阶段
71         //window.event.cancelBubble = true; //取消冒泡阶段
72         divParent.addEventListener('click', divParentClick, true);
73         oBody.addEventListener('click', oBodyClick, true);
74     </script>
75 </body>
事件冒泡演示代码

1、捕获阶段

  当鼠标在divA上触发点击事件时,首先捕捉到该事件的是根节点,也就是body元素,然后事件逐层向下传递,先到divParent,再到divA,这是捕获阶段。

  ☞ 事件的触发顺序,currentTarget和target属性的区别。

2、目标阶段

  当到达divA后,会查看是不是目标阶段,这就是目标阶段。该阶段就是找到事件最底层的节点,如果这个节点中定义了事件监听,那么就触发事件,调用事件处理函数。

3、冒泡阶段

  在处理了目标阶段的事件后就进入了冒泡阶段,之所以称之为冒泡,是因为它沿着原来的路径回溯。先到父节点divParent,直到根节点为止,这个过程就像是冒泡。

  要触发冒泡阶段的事件,就必须设置addEventListener()方法注册事件时参数useCapture为false。

1 divA.addEventListener('click', divAClick, false);
2 divParent.addEventListener('click', divParentClick, false);
3 oBody.addEventListener('click', oBodyClick, false);

  事件触发的顺序是一个冒泡过程。可以使用 cancelBubble 属性取消冒泡阶段,该属性要在注册事件监听程序后定义。

1 divA.addEventListener('click', divAClick, false);
2 window.event.cancelBubble = true; //取消冒泡阶段
3 divParent.addEventListener('click', divParentClick, false);
4 oBody.addEventListener('click', oBodyClick, false);

  W3C DOM使用stopPropagation()方法取消冒泡阶段:

window.event.stopPropagation(); //取消冒泡阶段

  

posted on 2015-06-17 16:39  如果你知道  阅读(137)  评论(0)    收藏  举报