MDN 对Mutation Observer 的描述如下:
Mutation Observer 提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。
换言之,这就是一个 DOM元素变化的监听器,当被观察的目标 DOM 发生改变时就可以执行指定的逻辑。
首先我们可以看一下Mutation Observer的结构
MutationObserver是一个构造函数,他的实例会有 disconnect、observe和 takeRecords 三个方法
constructor
构造函数接收一个函数,用于在 DOM 变化时执行,该函数有两个参数一个是描述所有被触发改动的 MutationRecord
对象数组,另一个是调用该函数的 MutationObserver
对象
function DOMHandler(mutationList, observer) {
mutationList.forEach((mutation) => {
switch(mutation.type) {
case 'childList':
// 从树上添加或移除一个或更多的子节点
console.log('结点变更')
break;
case 'attributes':
// mutation.target 中某节点的一个属性值被更改
console.log('属性变更')
break;
}
});
}
const observer = new MutationObserver(DOMHandler)
observe
mutationObserver.observe(target[, options])
- target: DOM 树中的一个要观察变化的 DOM
Node
(可能是一个Element
),或者是被观察的子节点树的根节点。 - options: 一个可选的
MutationObserverInit
对象,此对象的配置项描述了 DOM 的哪些变化应该提供给当前观察者的callback
(MDN 说是可选,但是在 chrome 控制台执行时报错必须有至少一个配置项)。
const node1 = document.getElementById('box')
observer.observe(node1, {attributes: true})
node1.setAttribute('name', '张三')
然后我们来在元素面板给node1 添加一个属性,此时属性变更触发了回调
disconnect
阻止 MutationObserver
实例继续接收的通知,直到再次调用其 observe()
方法,该观察者对象包含的回调函数都不会再被调用。
observer.disconnect()
node1.setAttribute('name', 'king')
调用之后再元素版本修改属性都不会再次触发之前的回调
takeRecords
返回已检测到但尚未由观察者的回调函数处理的所有匹配 DOM 更改的列表,使变更队列保持为空。
observer.observe(node, {attributes: true})
node.setAttribute('name', 'king')
const notices = observer.takeRecords()
由此可以看出,DOM 变化之后并不是立即通知执行回调,而是等主线程代码执行完毕再通知,所以 takeRecords 可以将通知提前拦截。
附:observe可接受的 options
属性 | 说明 | 默认值 |
---|---|---|
attributes | 设为 true 以观察受监视元素的属性值变更。 | 默认值为 false。 |
attributeFilter | 要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知。 | 无默认值。 |
characterData | 设为 true 以监视指定目标节点或子节点树中节点所包含的字符数据的变化。 | 无默认值 |
childList | 设为 true 以监视目标节点(如果 subtree 为 true,则包含子孙节点)添加或删除新的子节点。 | 默认值为 false。 |
subtree | 的其他值也会作用于此子树下的所有节点,而不仅仅只作用于目标节点。 | 默认值为 false。 |