为什么捕获阶段不会被 event.stopPropagation 中断?



如果运行此代码并单击p,则会执行整个捕获阶段,但在div上会按预期停止冒泡阶段。此代码有什么问题?

for(let elem of document.querySelectorAll('*')) {
elem.addEventListener("click", e => alert(`Capturing: ${elem.tagName}`), true);
elem.addEventListener("click", e => alert(`Bubbling: ${elem.tagName}`));
}
<form>FORM
<div onclick="event.stopPropagation()">DIV
<p>P</p>
</div>
</form>

捕获阶段不会中断,因为在现代浏览器中,事件默认在冒泡阶段注册(因此<div>元素中的onclick()事件不会与在捕获阶段注册的单独事件处理程序交互)。

我不知道有什么方法可以通过html属性注册捕获阶段事件处理程序(除了在某些较旧的浏览器中,默认情况下在捕获阶段注册事件)。

请参阅下面的代码片段以获得代码的修改版本,我认为这可能是您最初想要的。您将看到,此代码在捕获阶段和冒泡阶段处理程序中调用stopPropagation()(在这两种情况下都会产生预期结果)。

for (const elem of document.querySelectorAll('*')) {
elem.addEventListener('click', (event) => {
if (elem.tagName === 'DIV') {
event.stopPropagation();
}

console.log(`Capturing: ${elem.tagName}`);
}, true);

elem.addEventListener('click', (event) => {
if (elem.tagName === 'DIV') {
event.stopPropagation();
}

console.log(`Bubbling: ${elem.tagName}`);
});
}
<form>
form
<div>
div (click here)
<p>p</p>
</div>
</form>

在捕获阶段,浏览器从最外层的父元素开始处理处理程序,因此它不会遇到stopPropagation(),直到它已经处理了所有父元素<html><body>等的click处理程序。

在冒泡阶段,它处理事件处理程序,从单击的元素开始,通过父元素向外移动。

相关内容

  • 没有找到相关文章

最新更新