MutationObserver: observe() 方法
MutationObserver 的 observe() 方法用于配置 MutationObserver 的回调,使其开始接收与给定选项匹配的 DOM 更改通知。
根据配置,观察者可以监视 DOM 树中的单个 Node,或者监视该节点及其部分或全部后代节点。同一个节点可以被多个观察者监视,同一个 MutationObserver 可以通过多次调用 observe() 来监视 DOM 树不同部分或不同类型的更改。
要停止 MutationObserver(使其不再触发任何回调),请调用 MutationObserver.disconnect()。
语法
observe(target, options)
参数
目标options-
一个对象,提供描述哪些 DOM 变异应该报告给
mutationObserver的callback的选项。在调用observe()时,至少必须将childList、attributes和/或characterData中的一个设置为true。否则,将抛出TypeError异常。选项如下:
subtree可选-
设置为
true可将监视范围扩展到以target为根的整个节点子树。所有其他属性也将扩展到子树中的所有节点,而不仅仅应用于target节点。默认值为false。请注意,如果target的后代节点被移除,该后代子树中的更改将继续被观察,直到关于移除本身的通知被传递为止。 childList可选-
设置为
true可监视目标节点(如果subtree为true,则监视其后代节点)的子节点添加或现有子节点移除。默认值为false。 attributes可选-
设置为
true可监视被监视节点上属性值的更改。默认值为true,如果指定了attributeFilter或attributeOldValue中的任何一个,否则默认值为false。 attributeFilter可选-
要监视的特定属性名称数组。如果未包含此属性,则所有属性的更改都会导致变异通知。
attributeOldValue可选-
设置为
true可记录监视节点属性值更改时任何属性的先前值;有关监视属性更改并记录值的示例,请参见 监视属性值。默认值为false。 characterData可选-
设置为
true可监视指定的节点(如果subtree为true,则监视其后代节点)中包含的字符数据的更改。默认值为true,如果指定了characterDataOldValue,否则默认值为false。 characterDataOldValue可选-
设置为
true可记录被监视节点文本值更改时的先前文本值。默认值为false。
返回值
无(undefined)。
异常
TypeError-
在以下任何情况下抛出
options的配置导致实际上没有任何内容被监视。(例如,如果childList、attributes和characterData都为false。)options.attributes的值为false(表示不监视属性更改),但attributeOldValue为true和/或attributeFilter存在。characterDataOldValue选项为true但characterData为false(表示不监视字符更改)。
示例
基本用法
在此示例中,我们演示了如何在设置好 MutationObserver 实例后,调用其 observe() 方法,并传入一个目标元素和一个 options 对象。
// create a new instance of `MutationObserver` named `observer`,
// passing it a callback function
const observer = new MutationObserver(() => {
console.log("callback that runs when observer is triggered");
});
// call `observe()`, passing it the element to observe, and the options object
observer.observe(document.querySelector("#element-to-observe"), {
subtree: true,
childList: true,
});
使用 subtree 时移除的后代节点
如果您使用 subtree 选项监视一个节点,即使该子树的一部分已被移除,您仍将收到该节点后代节点的更改通知。但是,一旦关于移除的通知被传递,该已分离子树的进一步更改将不再触发观察者。
这可以防止您错过在连接断开后、您有机会专门开始监视已移动节点或子树以进行更改之前发生的更改。理论上,这意味着如果您跟踪描述发生的更改的 MutationRecord 对象,您应该能够“撤销”更改,将 DOM 恢复到其初始状态。
<div id="target">
<div id="child"></div>
</div>
const target = document.getElementById("target");
const child = document.getElementById("child");
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log(mutation.type, mutation.target.id, mutation.attributeName);
if (mutation.type === "childList" && mutation.target.id === "target") {
// After receiving the notification that the child was removed,
// further modifications to the detached subtree no longer trigger the observer.
child.setAttribute("data-bar", "");
}
});
});
observer.observe(target, {
attributes: true,
childList: true,
subtree: true,
});
target.removeChild(child);
// This change happens before the "childList target" notification is delivered,
// so it will also trigger the observer.
child.setAttribute("data-foo", "");
// Output:
// childList target null
// attributes child data-foo
// There is no "attributes child data-bar" notification.
使用 attributeFilter
在此示例中,设置了一个 Mutation Observer 来监视显示聊天室用户名称的子树中任何元素的 status 和 username 属性的更改。例如,这可以让代码反映用户昵称的更改,或将其标记为离开键盘 (AFK) 或离线。
function callback(mutationList) {
mutationList.forEach((mutation) => {
switch (mutation.type) {
case "attributes":
switch (mutation.attributeName) {
case "status":
userStatusChanged(mutation.target.username, mutation.target.status);
break;
case "username":
usernameChanged(mutation.oldValue, mutation.target.username);
break;
}
break;
}
});
}
const userListElement = document.querySelector("#user-list");
const observer = new MutationObserver(callback);
observer.observe(userListElement, {
attributeFilter: ["status", "username"],
attributeOldValue: true,
subtree: true,
});
监视属性值
在此示例中,我们监视一个元素以获取属性值更改,并添加一个按钮,在元素的 dir 属性("ltr" 和 "rtl")之间进行切换。在观察者的回调函数中,我们记录了属性的旧值。
HTML
<button id="toggle">Toggle direction</button><br />
<div id="container">
<input type="text" id="rhubarb" dir="ltr" value="Tofu" />
</div>
<pre id="output"></pre>
CSS
body {
background-color: paleturquoise;
}
button,
input,
pre {
margin: 0.5rem;
}
JavaScript
const toggle = document.querySelector("#toggle");
const rhubarb = document.querySelector("#rhubarb");
const observerTarget = document.querySelector("#container");
const output = document.querySelector("#output");
toggle.addEventListener("click", () => {
rhubarb.dir = rhubarb.dir === "ltr" ? "rtl" : "ltr";
});
const config = {
subtree: true,
attributeOldValue: true,
};
const callback = (mutationList) => {
for (const mutation of mutationList) {
if (mutation.type === "attributes") {
output.textContent = `The ${mutation.attributeName} attribute was modified from "${mutation.oldValue}".`;
}
}
};
const observer = new MutationObserver(callback);
observer.observe(observerTarget, config);
结果
规范
| 规范 |
|---|
| DOM # ref-for-dom-mutationobserver-observe② |
浏览器兼容性
加载中…