当我在stopImmediatePropagation
中使用document
时:
document.addEventListener('click', function (e) {
console.log('bubble');
});
document.addEventListener('click', function (e) {
console.log('capture');
e.stopImmediatePropagation();
}, true);
当我点击时,输出为:
capture
但是当我在stopImmediatePropagation
元素中使用p
时:
document.querySelector('p').addEventListener('click', function (e) {
console.log('bubble');
});
document.querySelector('p').addEventListener('click', function (e) {
console.log('capture');
e.stopImmediatePropagation();
}, true);
当我点击页面中的“p”元素时,输出为:
bubble
capture
谁能告诉我为什么?谢谢
答案 0 :(得分:4)
正如我已经提到的in my comment,一个事件经历了三个阶段:
在specification中可以很好地显示:
目标阶段似乎是DOM Level 3事件规范中的新功能,但它才是最重要的。
由于<p>
元素是第二种情况下的目标,因此两个事件处理程序都在目标阶段执行,而不是捕获或冒泡阶段。规范说事件处理程序应该按它们绑定的顺序执行。由于首先绑定“冒泡”事件处理程序,因此首先执行它。在第二个事件处理程序中调用stopImmediatePropagation
没有任何效果,因为没有其他处理程序要执行。这也解释了为什么输出的顺序是
bubble
capture
事实上,if we log the event.eventPhase
property instead,我们得到了
2
2
,其中
interface Event {
// PhaseType
const unsigned short NONE = 0;
const unsigned short CAPTURING_PHASE = 1;
const unsigned short AT_TARGET = 2;
const unsigned short BUBBLING_PHASE = 3;
[...]
If you change the order of the event handlers, it works as expected,但不是因为它们在不同的阶段执行,而是因为首先执行调用stopImmediatePropagation
的处理程序。
将处理程序绑定到document
时它“有效”,因为document
永远不是事件的目标。单击空文档时,目标是<html>
或<body>
元素。