阅读本文需要理解事件流动机制,可以查阅之前的DOM Event:事件流动(Event Flow)。
我们知道一个事件被浏览器捕获后会元素间流动,像这样:
document 1 7
v ^
body 2 6
v ^
div 3 5
v ^
button 4
事件会依次在这些元素间触发。
但我们有没有可能在中间阻止事件的继续传递呢?答案是有的,Event接口提供了两个阻止事件流动相关的API:
-
stopPropagation
,终止事件在元素间的传递,但同一元素上的监听能继续触发 -
stopImmediatePropagation
,终止事件
stopPropagation
该方法停止事件在元素间传递,但同一元素上的监听能继续触发。例如:
// button上监听并调用stopPropagation
buttonElement.addEventListener('click', (event) => {
console.log('1');
event.stopPropagation();
});
// button上继续监听,不会被上面的stopPropagation影响
buttonElement.addEventListener('click', (event) => {
console.log('2');
});
// div上监听,事件已不能传到这里
divElement.addEventListener('click', (event) => {
console.log('3');
});
上面这段代码的输出是:
1
2
stopImmediatePropagation
该方法会直接终止事件。事件不但不能在元素间传递,就算在同一元素上的后续监听都会被取消:
// button上监听并调用stopImmediatePropagation
buttonElement.addEventListener('click', (event) => {
console.log('1');
event.stopImmediatePropagation();
});
// button上继续监听,因stopImmediatePropagation的调用不会被执行
buttonElement.addEventListener('click', (event) => {
console.log('2');
});
// div上监听,事件已不能传到这里
divElement.addEventListener('click', (event) => {
console.log('3');
});
上面这段代码的输出是:
1
注意,上述两个事件只是停止了事件流动,而没有“阻止浏览器默认行为”(prevent default browser events);若你想阻止元素的默认行为,你依然需要额外调用preventDefault
。