问题:如果三个嵌套的div(div100>div10>div1),每个div都绑定了方法,那点击div1触发方法的顺序如何?
介绍:W3C标准的浏览器(非IE)中,JS的执行会经历三个阶段:捕获阶段,目标阶段,冒泡阶段。这三个阶段成为JS执行的事件流。
默认规则:JS的事件一般都是在冒泡阶段触发执行。
词汇:Bubble(冒泡),Capture(捕获),propagation(传播)。
答案:点击div1,方法执行顺序一般是div1->div10->div100。(如果存在监听函数addEventListeren,让父级元素在捕获阶段执行,则执行顺序不同。)
起航:浏览器的事件流(如图1所示)
图1 浏览器事件流机制
例子1:正常情况(冒泡阶段)
//HTML代码
<div class="div100" οnclick="alert('div100->Bubble')"> //父父级
<div class="div10" οnclick="alert('div10->Bubble')"> //父级
<div class="div1" οnclick="alert('div1->Bubble')"> //子级
点击
</div>
</div>
</div>
//CSS代码
.div100{
width: 300px;
height: 300px;
margin: 0 auto;
padding: 100px;
background-color: #aaa;
}
.div10{
width: 100px;
height: 100px;
padding: 100px;
background-color: #ccc;
}
.div1{
width: 100px;
height: 100px;
background-color: #eee;
text-align: center;
line-height: 100px;
cursor: pointer;
color: #888;
}
执行顺序:alert('div1->Bubble')->alert('div10->Bubble')->alert('div100->Bubble')。
原因:在点击div1时,浏览器JS开始进入捕获流,寻找是否存在捕获阶段需要执行的方法,由于不存在,而方法都默认在冒泡阶段执行,所以执行顺序如上述。
例子2:在例子1的情况下,追加下列JS代码。(捕获阶段)
window.onload = function(){
var div100 = document.getElementsByClassName('div100')[0];
div100.addEventListener('click', function(){alert('div100->Capture')}, true); //('事件','方法','是否捕获')
}
执行顺序:alert('div100->Capture')->alert('div1->Bubble')->alert('div10->Bubble')->alert('div100->Bubble')。
原因:在点击div1时,浏览器JS开始进入捕获流,寻找是否存在捕获阶段需要执行的方法,由于存在div100的捕获阶段需要执行的方法,执行完div100捕获的方法,再依次执行冒泡阶段的方法,所以执行顺序如上述。
例子3:在例子1的情况下,追加下列JS代码。(目标阶段)
window.onload = function(){
var div100 = document.getElementsByClassName('div100')[0];
var div10 = document.getElementsByClassName('div10')[0];
var div1 = document.getElementsByClassName('div1')[0];
div100.addEventListener('click', function(){alert('div100->Capture')}, true);
div10.addEventListener('click', function(){alert('div10->Capture')}, true);
div1.addEventListener('click', function(){alert('div1->Capture')}, true);
}
执行顺序:
alert('div100->Capture')->alert('div10->Capture')->alert('div1->Bubble')->
alert('div1->Capture')->alert('div10->Bubble')->alert('div100->Bubble')。
原因:
1.在点击div1时,浏览器JS开始进入捕获流,执行完div100和div10的捕获方法后。
2.进入目标阶段,该阶段则根据方法的编写先后执行,由于window.onload是在html代码编写完再编写,所以alert('div1->Bubble')先于alert('div1->Capture')执行。
3.依次执行冒泡阶段函数。div10和div100的冒泡方法。
误区:event.stopPropagation
JQ解释:防止事件冒泡到DOM树上,也就是不触发的任何前辈元素上的事件处理函数。
个人见解:防止事件传播,所以当执行stopPropagation后,就不会继续传播事件,也就是捕获阶段,目标阶段,冒泡阶段都可能被阻止。
推荐阅读: