MutationObserver监听DOM
概念
MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。
但是,它与事件有一个本质不同:
事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;
而Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。
使用方式
// 使用时,首先使用`MutationObserver`构造函数
// 新建一个观察器实例,同时指定这个实例的回调函数
const observer = new MutationObserver((mutations, observer) => {
mutations.forEach((mutation) => {
console.log(mutation);
});
});
// 获取一个dom
const myDom = document.querySelector('myDom');
// 需要观察变动的类型
const options = {
'childList': true,
'attributes': true
};
// 启动观察
observer.observe(myDom, options);上面代码中,new MutationObserver() 表示创建一个监听实例,它必需要有一个回调函数,该函数有两个参数,第一个是变动类型的数组,第二个是观察器实例本身,这个函数在每次DOM变动时被调用
方法
observe
observe()方法用来启动监听,它接受两个参数,第一个参数为需要监听的DOM节点,第二个参数为需要观察变动的类型
观察变动的类型有以下几种:
childList:布尔值,表示子节点的变动(指新增,删除或者更改)。attributes:布尔值,表示属性的变动。characterData:布尔值,表示节点内容或节点文本的变动。subtree:布尔值,表示是否将该观察器应用于该节点的所有后代节点。attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。attributeFilter:数组,表示需要观察的特定属性(比如['class','src']),当该数组不为空时,attributes默认为true。
注意想要观察哪一种变动类型,就在
option对象中指定它的值为true。需要注意的是,必须同时指定
childList、attributes和characterData中的一种或多种,若均未指定将报错。
takeRecords
takeRecords方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。
observer.takeRecords();disconnect
disconnect方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。
observer.disconnect();MutationRecord 对象
new MutationObserver()中回调函数的第一个参数获取的就是 MutationRecord 对象
DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例),该实例包含了与变动相关的所有信息。 Mutation Observer 处理的就是一个个MutationRecord 实例所组成的数组。
MutationRecord对象包含了DOM的相关信息,有如下属性:
type:观察的变动类型(attribute、characterData或者childList)。target:发生变动的DOM节点。addedNodes:新增的DOM节点。removedNodes:删除的DOM节点。previousSibling:前一个同级节点,如果没有则返回null。nextSibling:下一个同级节点,如果没有则返回null。attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。
示例
监听html根节点的class属性变化
let element = document.querySelector('html');
let observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type == 'attributes') {
console.log('当前class为', element.className)
}
});
});
observer.observe(element, {
attributeFilter: ['class']
});