MutationObserver 监听位置
什么是 MutationObserver
MutationObserver 用于监听 DOM 树的修改,可用于监听元素位置的变化。
一、基本用法
MutationObserver 是个构造函数。需要使用 new 关键字调用,通过 observe 方法指定监听的元素。
mutationObserver.observe(target, options)
target
: 监听的元素options
: 监听的范围(必须有childList
、attributes
和characterData
中一种或多种)childList
(boolean),表示是否监听子节点的变动;attributes
(boolean),表示是否监属性的变动;characterData
(boolean),表示是否监听节点内容/文本的变动;subtree
(boolean),表示是否监听所有后代节点;attributeFilter
(array),表示观察特定属性;attributeOldValue
(boolean),表示观察 attributes 变动时,是否需要记录变动前的属性值;characterDataOldValue
(boolean),表示观察 characterData 变动,是否需要记录变动前的值;
注意
MutationObserver 的 options
是必选项,而 ResizeObserver 是可选。
const mutationObserver = new MutationObserver(entries => {
console.log(entries)
});
const options = {
childList: true, // 子节点的变动(新增、删除或者更改)
attributes: true, // 属性的变动
characterData: true, // 节点内容或节点文本的变动
subtree: true, // 是否将观察器应用于该节点的所有后代节点
attributeFilter: ['class', 'style'], // 观察特定属性
attributeOldValue: true, // 观察 attributes 变动时,是否需要记录变动前的属性值
characterDataOldValue: true // 观察 characterData 变动,是否需要记录变动前的值
}
mutationObserver.observe(document.querySelector('#box'), options)
当该 DOM 元素节点增减、属性/宽高/内容的变化时输出:

其中,几个比较关键的属性如下:
attributeName
: 表示修改的属性名称;target
: 修改的目标;type
: 类型。
二、获取监听记录
在终止 MutationObserver 之前,可通过 takeRecords 获取已有的 mutationRecords 记录:
const mutationObserver = new MutationObserver((mutation) => console.log(mutation))
mutationObserver.observe(document.body, {
attributes: true
})
document.body.className = 'main'
document.body.className = 'container'
document.body.className = 'box'
// 获取修改记录
const mutationRecords = mutationObserver.takeRecords()
console.log(mutationRecords) // [MutationRecord, MutationRecord, MutationRecord]
三、取消监听
与 removeEventListener
同理,需要取消监听。
可通过 disconnect 取消 mutationObserver 监听。
const mutationObserver = new MutationObserver(entries => {
console.log(entries)
});
mutationObserver.observe(document.querySelector('#box'), {
attributes: true
})
mutationObserver.observe(document.body, {
attributes: true
})
// 2s 后取消所有节点的监听
setTimeout(() => {
mutationObserver.disconnect()
}, 2000)
在 React 中使用时,一般会在 useEffect 的返回值中对 MutationObserver 统一销毁:
useEffect(() => {
const mutationObserver = new MutationObserver(entries => {
console.log(entries)
});
mutationObserver.observe((triggerNode.current as any), {
attributes: true,
childList: false,
subtree: false
})
return () => mutationObserver.disconnect()
}, [])