开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
前言
MutationObserver 是一个内建对象,它观察 DOM 元素,并在检测到更改时触发回调。
我们将首先看一下语法,然后探究一个实际的用例,以了解它在什么地方有用。
语法
MutationObserver 使用简单。
首先,我们创建一个带有回调函数的观察器:
let observer = new MutationObserver(callback);
然后将其附加到一个 DOM 节点:
observer.observe(node, config);
config 是一个具有布尔选项的对象,该布尔选项表示“将对哪些更改做出反应”:
childList——node的直接子节点的更改,subtree——node的所有后代的更改,attributes——node的特性(attribute),attributeFilter—— 特性名称数组,只观察选定的特性。characterData—— 是否观察node.data(文本内容),
其他几个选项:
attributeOldValue—— 如果为true,则将特性的旧值和新值都传递给回调(参见下文),否则只传新值(需要attributes选项),characterDataOldValue—— 如果为true,则将node.data的旧值和新值都传递给回调(参见下文),否则只传新值(需要characterData选项)。
然后,在发生任何更改后,将执行“回调”:更改被作为一个 MutationRecord 对象列表传入第一个参数,而观察器自身作为第二个参数。
MutationRecord 对象具有以下属性:
-
type—— 变动类型,以下类型之一:"attributes":特性被修改了,"characterData":数据被修改了,用于文本节点,"childList":添加/删除了子元素。
-
target—— 更改发生在何处:"attributes"所在的元素,或"characterData"所在的文本节点,或"childList"变动所在的元素, -
addedNodes/removedNodes—— 添加/删除的节点, -
previousSibling/nextSibling—— 添加/删除的节点的上一个/下一个兄弟节点, -
attributeName/attributeNamespace—— 被更改的特性的名称/命名空间(用于 XML), -
oldValue—— 之前的值,仅适用于特性或文本更改,如果设置了相应选项attributeOldValue/characterDataOldValue。
例如,这里有一个 <div>,它具有 contentEditable 特性。该特性使我们可以聚焦和编辑元素。
<div contentEditable id="elem">Click and <b>edit</b>, please</div>
<script>
let observer = new MutationObserver(mutationRecords => {
console.log(mutationRecords); // console.log(the changes)
});
// 观察除了特性之外的所有变动
observer.observe(elem, {
childList: true, // 观察直接子节点
subtree: true, // 及其更低的后代节点
characterDataOldValue: true // 将旧的数据传递给回调
});
</script>
如果我们在浏览器中运行上面这段代码,并聚焦到给定的 <div> 上,然后更改 <b>edit</b> 中的文本,console.log 将显示一个变动:
mutationRecords = [{
type: "characterData",
oldValue: "edit",
target: <text node>,
// 其他属性为空
}];
如果我们进行更复杂的编辑操作,例如删除 <b>edit</b>,那么变动事件可能会包含多个变动记录:
mutationRecords = [{
type: "childList",
target: <div#elem>,
removedNodes: [<b>],
nextSibling: <text node>,
previousSibling: <text node>
// 其他属性为空
}, {
type: "characterData"
target: <text node>
// ...变动的详细信息取决于浏览器如何处理此类删除
// 它可能是将两个相邻的文本节点 "edit " 和 ", please" 合并成一个节点,
// 或者可能将它们留在单独的文本节点中
}];
因此,MutationObserver 允许对 DOM 子树中的任何更改作出反应。