43

我知道 MutationObservers 回调可能会在 DOM 更改后的某个时间被调用。但问题是:这些回调的时机是什么?回调是否进入浏览器的事件队列?如果是这样,他们什么时候进入队列?

是回调:

  • 在 DOM 突变发生后立即调用,
  • 操作 DOM 的函数完成后立即调用,
  • 调用堆栈为空时立即调用,
  • 在 DOM 突变发生后立即排队,
  • 操作 DOM 的函数完成后立即入队,或者
  • 在其他时间?

例如,如果执行以下代码(此处定义了 setZeroTimeout):

var target = document.body;

new MutationObserver(function(mutations) {
  console.log('MutationObserver');
}).observe(target, {
  attributes: true,
  childList: true,
  characterData: true
});


// Post message
setZeroTimeout(function () { console.log('message event'); });
// DOM mutation
target.setAttribute("data-test", "value");

“MutationObserver”应该在“消息事件”之前还是之后打印?或者它是实现定义的?

我在 Chromium 26 上的“消息事件”之前得到“MutationObserver”,尽管 DOM 突变是在消息发布之后。也许这表明 MutationObserver 回调没有使用事件队列。

我搜索了 HTML 规范、DOM 规范或浏览器实现文档,但没有找到与此行为相关的任何内容。

请问有关于 MutationObservers 回调时间的解释或文档吗?

4

2 回答 2

23

MutationObservers 异步触发但“很快”,这意味着它们在队列中的其他事物之前触发,例如布局、绘制或触发事件。

这改善了同步的损失,因为在观察者有机会做出反应之前,您不必担心屏幕闪烁或其他坏事发生。

在开发人员说明中,他们谈到了“微任务结束”时序模型。我同意这没有很好的记录。

于 2013-04-08T21:45:25.867 回答
19

两年后,我将根据WHATWG 更新的 DOM 规范回答我自己的问题。

如规范所示:

要将突变观察者复合微任务排队,请运行以下步骤:

  1. 如果设置了变异观察者复合微任务队列标志,则终止这些步骤。
  2. 设置变异观察者复合微任务队列标志。
  3. 排队一个复合微任务以通知突变观察者。

而“对复合微任务进行排队”链接到HTML 规范中解释微任务队列模型的部分。

因此,我们可以得出结论,MutationObserver回调是作为微任务触发的,这确实比上面@Scott Miles 的答案所建议的任务队列任务更快。

为了进一步了解事件循环和处理模型, HTML 规范的事件循环部分将是完美的。

就个人而言,我很高兴看到MutationObservers 是标准的一部分,并且有一个有据可查且一致的时序模型。大多数现代浏览器都支持s MutationObserver,我认为它们现在非常适合生产使用。

于 2015-12-16T12:07:52.537 回答