【问题标题】:Does stopPropagation() stops executing the event from capture phase?stopPropagation() 是否从捕获阶段停止执行事件?
【发布时间】:2021-02-28 14:06:36
【问题描述】:

这张图片取自 DOM ENLIGHTENMENT 书。它说 stopPropagation() 将停止捕获和冒泡事件流阶段。

我知道stopPropagation()会停止传播,不会在冒泡阶段执行回调函数。

但是在下面的代码sn-p中,在按钮上使用了stopPropagation()之后,body事件回调方法还是被执行了。

stopPropagation() 是否也会在捕获阶段停止事件流阶段?

const button = document.querySelector('button');

document.body.addEventListener('click', e => {
  console.log('Body event triggered');
}, true);

button.addEventListener('click', e => {
  console.log('button is clicked 1');
});

button.addEventListener('click', e => {
  e.stopPropagation();
  console.log('button is clicked 2');
});

button.addEventListener('click', e => {
  console.log('button is clicked 3');
});
<button> click me </button>

【问题讨论】:

    标签: javascript dom


    【解决方案1】:

    但是在下面的代码sn-p中,在按钮上使用了stopPropagation()之后,body事件回调方法还是被执行了。

    您所有的 button click 处理程序都是目标/冒泡处理程序,而不是捕获处理程序。在您调用stopPropagation 时,捕获阶段已经完成。如果您在 document.body 上有一个目标/冒泡处理程序,您会看到它没有被调用。

    请注意,传播与从一个元素移动到其父元素(冒泡)或后代(捕获)有关,但不会影响处理 same 元素上的其他处理程序,这就是您的处理程序调用 @ 987654328@ 没有在button both 触发时停止其他处理程序。 (如果你使用了stopImmediatePropagation,你会停止第三个处理程序,因为它会立即停止,即使是在当前元素的处理程序中间。)

    这是一个在捕获阶段取消传播的示例:

    const div = document.getElementById("middle");
    const button = document.getElementById("button");
    
    // Capture phase on body
    document.body.addEventListener("click", e => {
        console.log("body capture handler");
    }, true);
    
    // Target/bubbling phase on body
    document.body.addEventListener("click", e => {
        console.log("body target/bubbling handler");
    });
    
    // Capture phase on middle
    middle.addEventListener("click", e => {
        console.log("middle capture handler - stopping propagation");
        e.stopPropagation();
    }, true);
    
    // Target/bubbling phase on middle
    middle.addEventListener("click", e => {
        console.log("middle target/bubbling handler");
    });
    
    // Capture phase on button
    button.addEventListener("click", e => {
        console.log("button capture handler");
    }, true);
    
    // Target/bubbling phase on button
    button.addEventListener("click", e => {
        console.log("button target/bubbling handler");
    });
    <div id="middle">
        <input type="button" id="button" value="Click me">
    </div>

    注意:

    1. button 上的捕获阶段处理程序没有触发,因为传播在到达那里之前就停止了;和

    2. 没有触发目标/冒泡阶段处理程序,因为传播在目标阶段之前停止(因此在冒泡阶段之前)。

    我发现DOM3 Events spec 中的这张图表对于描绘这些东西非常有用:

    【讨论】:

    • 我使用true 作为addEventListener 的第三个参数用于capturing 阶段。但它仍然运行。是不是因为在button上的e.stopPropagation()之前已经处理过了
    • @DeC - 是的,这就是我在答案的第二句话中所说的(“在您调用 stopPropagation 时,捕获阶段已经完成。”)在上图中,你从最上面的红色箭头开始。如您所见,第三个箭头将您带到body,这是body 上的捕获阶段处理程序运行的时间。然后继续捕获,直到到达您的button(在图中它是td)。然后你的每个button 处理程序运行,中间的一个停止传播。这意味着绿色箭头没有发生,但红色箭头已经发生。
    猜你喜欢
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多