我正在阅读 Jake Archibald 关于任务、微任务等的文章。在他的示例中,我们看到“控制台日志”以特定顺序打印基于用户的点击事件,而以不同的顺序打印以编程方式触发的点击事件。我请求是否有人可以更详细地解释一下这两种情况下的点击回调执行情况。
HTML
<div class="outer-test"><div class="inner-test"></div></div>
CSS
.outer-test {
background: #D4D4D4;
padding: 25px;
width: 92px;
margin: 0 auto;
}
.inner-test {
background: #ADADAD;
padding: 46px;
width: 0;
}
JS(第一种情况)
var outer = document.querySelector('.outer-test');
var inner = document.querySelector('.inner-test');
new MutationObserver(function() {
console.log('mutate');
}).observe(outer, {
attributes: true
});
function onClick() {
console.log('click');
setTimeout(function() {
console.log('timeout');
},0);
Promise.resolve().then(function() {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
JS(第二种情况)
var outer = document.querySelector('.outer-test');
var inner = document.querySelector('.inner-test');
new MutationObserver(function() {
console.log('mutate');
}).observe(outer, {
attributes: true
});
function onClick() {
console.log('click');
setTimeout(function() {
console.log('timeout');
},0);
Promise.resolve().then(function() {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
inner.click(); //<========
引用:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
最佳答案
.click() causes the event to dispatch synchronously, so the script that calls .click() is still in the stack between callbacks.
他浏览了答案,但基本上就是这样。我不会假装我完全理解细节,但当我读到它时:因为点击是在与设置事件监听器的代码相同的“框架”中的 JavaScript 中触发的,并且以这种方式触发事件是同步的回调之后直接运行,因为它不允许检查微任务队列的突变。
在第一种情况下,“设置”完成并且“框架”结束。因此,只有在浏览器中单击才会触发事件,然后这将在另一个框架中(异步)发生,并且由于此时没有其他“框架”正在运行,因此它会首先检查微任务队列中的突变。
The above rule ensures microtasks don't interrupt JavaScript that's mid-execution.
这似乎就是为什么没有这样做的原因,这是有道理的,因为它都是单线程的(你知道,有点),让“框架”完成是有意义的。
因此,奇怪之处在于以编程方式触发事件会强制所有事件进入同步状态。
关于javascript - 用户触发的 'click'事件回调的执行与编程触发的有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58292052/