点击时,输出 1 然后 2:
const myElem = document.getElementById("myElem")
myElem.addEventListener('click', () => queueMicrotask(() => console.log(1)));
window.addEventListener('click', () => console.log(2));
<button id="myElem">Click me</button>
如果
queueMicrotask
替换为 setTimeout
它输出 2 然后 1。这意味着冒泡发生在微任务中,而不是宏任务中。它是 DOM 规范的一部分还是只是浏览器实现细节?
最佳答案
在微队列任务中出现事件冒泡的唯一方法是,您在微任务任务队列中运行的代码中的元素上分派(dispatch)自定义事件,或者如果 mutation observers正在内部通知 DOM 已从微任务中修改(使用“slotchange”事件)。在这两种情况下,事件都是从正在执行的微任务中触发的,并且事件冒泡在 JavaScript 执行线程中同步发生。相反,“ native ”事件由浏览器触发并调用 event handlers asynchronously via the event loop .
发布的事件场景中缺少的是,如果为同一类型的本地事件添加了多个事件处理程序,则处理程序被称为 。来自事件循环 .因此,处理程序入队的任何微任务都将在处理程序调用的控制返回事件队列之前执行。
通过演示两个“单击”处理程序的事件流:
"use strict";
document.querySelector("div").addEventListener("click", click1);
window.addEventListener("click", click2 /*, {capture:true}*/ );
function click1(event) {
console.log("click1 called for div")
queueMicrotask( ()=> console.log("microtask1 executes"));
console.log("click1 exits");
}
function click2(event) {
console.log("click2 called for window")
queueMicrotask( ()=> console.log("microtask2 executes"));
console.log("click2 exits");
}
div {background-color: yellow}
<div>Click this div</div>
or click the window,
运行代码片段并单击 div 以确认 div 处理程序被调用、退出,并且它产生的微任务运行,然后在冒泡发生后调用窗口处理程序。请注意,虽然从事件循环中调用,但它们被调用的顺序将取决于是否使用事件捕获(在代码段中注释掉)。
如果替换
queueMicrotask
与 setTimeout
在帖子的第一次点击处理程序中,回调函数是不再 在返回事件循环之前在微任务队列中执行,允许事件循环在计时器回调之前调用第二个点击处理程序(对于在计时器到期之前生成的事件)。
关于javascript - 微任务中的事件会冒泡吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70734518/