先上一张经典的js事件捕获和冒泡图
举个例子
<div id="box1">
box1
<div id="box2">box2</div>
</div>
window.addEventListener(
'click',
() => {
console.log('window 冒泡');
},
false
);
window.addEventListener(
'click',
() => {
console.log('window 捕获');
},
true
);
document.addEventListener(
'click',
() => {
console.log('document 冒泡');
},
false
);
document.addEventListener(
'click',
() => {
console.log('document 捕获');
},
true
);
document.documentElement.addEventListener(
'click',
() => {
console.log('html 冒泡');
},
false
);
document.documentElement.addEventListener(
'click',
() => {
console.log('html 捕获');
},
true
);
document.body.addEventListener(
'click',
() => {
console.log('body 捕获');
},
true
);
document.body.addEventListener(
'click',
() => {
console.log('body 冒泡');
},
false
);
const box1 = document.getElementById('box1');
const box2 = document.getElementById('box2');
box1.addEventListener(
'click',
() => {
console.log('box1 冒泡');
},
false
);
box1.addEventListener(
'click',
() => {
console.log('box1 捕获');
},
true
);
box2.addEventListener(
'click',
() => {
console.log('box2 冒泡');
},
false
);
box2.addEventListener(
'click',
() => {
console.log('box2 捕获');
},
true
);
点击box2输出如下
//window 捕获
//document 捕获
//html 捕获
//body 捕获
//box1 捕获
//box2 冒泡
//box2 捕获
//box1 冒泡
//body 冒泡
//html 冒泡
//document 冒泡
//window 冒泡
点击box2,click事件先沿着window->document->html->body->box1->box2捕获前进,在捕获过程中执行相应的函数。
到达box2后,则按照事件绑定顺序执行函数。由于在box2上绑定的冒泡事件先于捕获事件,所以先执行冒泡事件上的函数。
在box2上的函数执行完后,click事件沿着box2->box1->body->html->document->window冒泡前进。
但是,不是所有的事件都像上面那样,有的事件就不支持冒泡,例如:
- 鼠标事件(
mouseleave
、mouseenter
) - 焦点事件(
blur
、focus
) - UI事件(
load
、unload
、scroll
、resize
)
可以用Event.bubbles
这个只读布尔值判断事件是否支持冒泡
- 焦点事件(
blur
、focus
) - UI事件(
load
、unload
、scroll
、resize
)
可以用Event.bubbles
这个只读布尔值判断事件是否支持冒泡