我很好奇 MutationObserver 接收到的一批突变是否按顺序返回。
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type); // are these in order?
});
});
谢谢!
不。不能保证它们是有序的,这让事情变得非常困难。
看一下这个例子,例如:
https://codepen.io/trusktr/pen/OJveVbv/d7f4cc48f8fa3b7462ae8043157ba05d
const connected = new Set
const disconnected = new Set
let scheduled = false
class XEl extends HTMLElement {
connectedCallback() {
this.o = new MutationObserver(changes => {
for (const change of changes) {
console.log('--- change for target', change.target.id)
for (const child of change.addedNodes) {
console.log('track added child', child)
connected.add(child)
}
for (const child of change.removedNodes) {
console.log('track removed child', child)
disconnected.add(child)
}
}
if (!scheduled) {
scheduled = true
queueMicrotask(() => {
console.log('--------------- MICROTASK MO')
scheduled = false
const allNodes = new Set([...connected, ...disconnected])
for (const child of allNodes) {
if (child.parentElement) {
if (disconnected.has(child)) console.log('child removed:', child)
if (connected.has(child)) console.log('child added:', child)
} else {
if (connected.has(child)) console.log('child added:', child)
if (disconnected.has(child)) console.log('child removed:', child)
}
}
connected.clear()
disconnected.clear()
})
}
})
this.o.observe(this, {childList: true})
}
disconnectedCallback() {
this.o.disconnect()
}
}
customElements.define('x-el', XEl)
setTimeout(() => {
queueMicrotask(() => console.log('--------------- MICROTASK before'))
const t = three
t.remove() // queue mutation for two
one.append(t) // queue mutation for one
t.remove() // queue mutation for one
two.append(t) // queue mutation for two
t.remove() // queue mutation for two
one.append(t) // queue mutation for one
t.remove() // queue mutation for one
two.append(t) // queue mutation for two
queueMicrotask(() => console.log('--------------- MICROTASK after'))
}, 1000)
<x-el id="one">
one
<x-el id="two">
two
<x-el id="three">
three
</x-el>
</x-el>
</x-el>
请注意,在控制台输出中,首先循环一个父元素的所有记录,然后循环另一个父元素的所有记录。
这与实际运行的代码完全不同,其中它在父级一和父级二之间交替。
顺便说一句,与 DOM Mutation Events 相比,Mutation Observer 非常难以使用。我坚信,可以创建一个类似于 Mutation Events 的、更直观、不影响性能的 API 版本,而不是 MutationObserver 的 childList API。
有关开发人员体验的 MutationObserver 复杂性与 Mutation Events 简单性的更多详细信息:
https://github.com/whatwg/dom/issues/1105
如果您同意,请表达对更简单 API 的需求!