通过addEventListener()方法为对象绑定的事件分为两种类型:冒泡和捕获,这是由函数的第三个参数决定的,默认为冒泡类型。为false时表示冒泡类型,为true时表示捕获类型。如果在多个对象上绑定冒泡或捕获事件,甚至在同一个对象上绑定冒泡和捕获事件,那么,事件的执行顺序会是什么样的呢?
统一的代码片段
<div id="a">a
<p id="p">p<p>
</div>
#a{
width:200px;
height:200px;
background:green;
}
#p{
height:100px;
width:100px;
background:maroon;
}
1. 全部对象上绑定为冒泡事件
document.getElementById('p').addEventListener('click',function(e){
console.log('p冒泡');
},false);
document.getElementById('a').addEventListener('click',function(e){
console.log('a冒泡');
},false);
说明:在p区域点击,打印顺序为:p冒泡、a冒泡;在a区域点击,打印:a冒泡
2. 全部对象上绑定为捕获事件
document.getElementById('p').addEventListener('click',function(e){
console.log('p捕获');
},true);
document.getElementById('a').addEventListener('click',function(e){
console.log('a捕获');
},true);
说明:在p区域点击,打印顺序为:a捕获、p捕获;在a区域点击,打印:a捕获
3. 冒泡与捕获事件混合一:捕获事件在外层对象上绑定
document.getElementById('p').addEventListener('click',function(e){
console.log('p冒泡');
},false);
document.getElementById('a').addEventListener('click',function(e){
console.log('a捕获');
},true);
说明:在p区域点击,打印顺序为:a捕获、p冒泡;在a区域点击,打印:a捕获
4.冒泡与捕获事件混合二:捕获事件在内层对象上绑定
document.getElementById('p').addEventListener('click',function(e){
console.log('p捕获');
},true);
document.getElementById('a').addEventListener('click',function(e){
console.log('a冒泡');
},false);
说明:在p区域点击,打印顺序为:p捕获、a冒泡;在a区域点击,打印:a冒泡
5. 全部对象上绑定为冒泡事件
// 绑定在同一对象上的两个类型的顺序无影响
document.getElementById('p').addEventListener('click',function(e){
console.log('p捕获');
},true);
document.getElementById('a').addEventListener('click',function(e){
console.log('a冒泡');
},false);
document.getElementById('a').addEventListener('click',function(e){
console.log('a捕获');
},true);
说明:在p区域点击,打印顺序为:a捕获、p捕获、a冒泡;在a区域点击,打印:a冒泡、a捕获
总结:
如果一个dom上只绑定了一个方式(冒泡或是捕获),那么点击内部的dom,会先触发外部的捕获事件,其次是被点击dom的事件(冒泡或捕获),点击最外层的dom则只触发该层的dom事件;如果一个dom上同时绑定两种方式的事件,那么点击该dom会先触发外层的捕获事件(如果没有,则先触发本层的冒泡事件,然后才是本层的捕获事件,最后才是外层的冒泡事件),点击在没有绑定两种方式的dom(绑定两种方式的dom处在内存)上,则先触发外层的捕获事件(如果没有则直接执行本层事件)。