stopImmediatePropagation在“document”和“p”元素中有不同的结果

时间:2014-06-16 01:41:56

标签: javascript dom javascript-events

当我在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

谁能告诉我为什么?谢谢

1 个答案:

答案 0 :(得分:4)

正如我已经提到的in my comment,一个事件经历了三个阶段:

  • 捕获阶段“事件对象必须通过目标的祖先从defaultView传播到目标的父级。”
  • 目标阶段“事件对象必须到达事件对象的事件目标。”
  • 冒泡阶段“事件对象以相反的顺序传播通过目标的祖先,从目标的父级开始并以defaultView结尾”

specification中可以很好地显示:

enter image description here

目标阶段似乎是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>元素。