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(); //取消冒泡阶段
浙公网安备 33010602011771号