郑州微网站制作,个人怎么进行网站建设,长春模板网站建设企业,做网站那个搜索引擎好Mutation Observer#xff08;变动观察者#xff09;
定义 Mutation Observer是一种JavaScript API#xff0c;用于异步监测DOM树的变动#xff0c;包括元素的添加、删除、属性变化等。当DOM发生变动时#xff0c;它可以触发回调函数#xff0c;允许你对变动作出响应。 …Mutation Observer变动观察者
定义 Mutation Observer是一种JavaScript API用于异步监测DOM树的变动包括元素的添加、删除、属性变化等。当DOM发生变动时它可以触发回调函数允许你对变动作出响应。 Mutation Observer的意义 Mutation Observer API 的设计意义就是用来替换掉在 DOM 3 事件规范中引入的 Mutation events。 你可能会问了为什么呢
这就要讲讲Mutation events了 先给大家看一Mutation events的简单用法
jcode
上面这段代码乍一看可能没什么问题确实也能实现监听改变的功能但是往深层次考虑它还是存在很多缺点。例如 兼容性问题 IE9 不支持 Mutation EventsMutation Events在较旧版本的Internet Explorer如IE9及更早版本中不受支持。这意味着如果我们使用IE9的浏览器运行这段代码将会失效。Webkit 内核不支持 DOMAttrModifiedWebkit内核浏览器如旧版本的Safari和Chrome不支持DOMAttrModified属性的Mutation Event。Firefox 不支持 DOMElementNameChanged 和 DOMAttributeNameChangedMozilla Firefox不支持DOMElementNameChanged和DOMAttributeNameChanged这两种Mutation Event。 性能问题 同步执行Mutation Events是同步执行的它们会在DOM发生变化时立即触发从事件队列中取出事件执行事件处理程序然后从队列中移除。如果DOM变化频繁每次事件都需要执行这些操作如果产生堵塞将会引起全局堵塞事件冒泡Mutation Events使用事件冒泡来传播事件。如果在事件冒泡过程中触发其他Mutation Events可能会导致事件处理程序的嵌套这可能会占用大量的JavaScript执行时间甚至导致浏览器线程阻塞。
Mutation Observer的出现就是为了代替Mutation events来弥补Mutation events的缺陷。而且Mutation Events能监听的DOM树结构变化Mutation Observer都能监听。
DOMAttrModified当元素的属性被修改时触发我们可以捕获属性值的更改。DOMAttributeNameChanged当元素的属性节点名称发生变化时触发可以检测到属性名称的修改。DOMCharacterDataModified当文本节点的内容发生变化时触发用于监视文本节点中的文本内容变化。DOMElementNameChanged当元素的节点名称发生变化时触发用于检测节点名称的修改。DOMNodeInserted当元素的子节点被插入到DOM树中时触发我们可以监测到新节点的添加。DOMNodeRemoved当元素的子节点被从DOM树中移除时触发用于检测节点的移除。DOMNodeInsertedIntoDocument当元素的子节点被插入到文档中时触发用于监视节点的插入操作。DOMSubtreeModified当DOM树的子树结构发生变化时触发我们可以捕获到更广泛的DOM树变化。
Mutation Observer的优点
兼容性好 实时监测DOM变动可以实时监测DOM树的变动而不需要轮询或事件监听器。灵活性可以精确地指定要观察的DOM元素以及要观察的变动类型。性能优好它通过异步执行回调函数来处理DOM变化不会阻塞主线程。
用法
1.创建Mutation Observer实例
首先我们需要创建一个Mutation Observer的实例。它需要一个回调函数作为参数这个回调函数会在DOM发生变动时被触发。
const observer new MutationObserver(callback);2.指定观察的目标元素和选项
observe(target, options) observe方法的作用是启动监听它接受两个参数。 第一个参数所要观察的 DOM 节点第二个参数一个配置对象指定所要观察的特定变动 然后我们需要指定要观察的目标元素和观察选项。观察选项是一个配置对象它包括以下属性 childList“boolean”(当目标元素的子元素发生添加或删除时触发回调。)attributes“boolean”(当目标元素的属性发生变化时触发回调。)subtree“boolean”(是否观察目标元素的子孙元素。)characterData“boolean”(当目标元素的文本内容发生变化时触发回调。)attributeOldValue“boolean”(表示观察attributes变动时是否需要记录变动前的属性值。)characterDataOldValue“boolean”(表示观察characterData变动时是否需要记录变动前的值。)attributeFilter“Array”(一个数组包含要观察的特定属性的名称。) const target document.querySelector(#elementToObserve);
const config {childList: true,attributes: true,subtree: true,characterData: true,attributeFilter: [data-custom]
};observer.observe(target, config);注意
必须同时指定childList、attributes和characterData中的一种或多种若未均指定将报错。对一个节点添加观察器就像使用addEventListener方法一样多次添加同一个观察器是无效的回调函数依然只会触发一次。但是如果指定不同的options对象就会被当作两个不同的观察器。
3.编写回调函数
回调函数会在DOM变动时被触发它接受两个参数mutationsList和observer。 mutationsList是一个Mutation Record对象的数组每个对象描述一个DOM变动。observer对观察器本身的引用。 MutationRecord 对象包含了以下属性 type一个字符串表示变化的类型可能是 attributes属性更改、childList子元素的添加或移除或 characterData文本节点的更改。target变化发生的目标元素。addedNodes一个 NodeList 对象包含了被添加的节点。仅当变化类型为 childList 时才存在。removedNodes一个 NodeList 对象包含了被移除的节点。仅当变化类型为 childList 时才存在。previousSibling变化前目标节点的前一个同级节点。仅当变化类型为 childList 时才存在。nextSibling变化前目标节点的下一个同级节点。仅当变化类型为 childList 时才存在。attributeName发生属性更改时的属性名称。仅当变化类型为 attributes 时才存在。oldValue属性更改前的旧值。仅当变化类型为 attributes 时才存在。attributeNamespace变化属性的命名空间。仅当变化类型为 attributes 时才存在。 const callback (mutationsList, observer) {mutationsList.forEach(mutation {if (mutation.type childList) {// 处理子元素的添加或删除} else if (mutation.type attributes) {// 处理属性变化}});
};4.disconnect()方法 disconnect() 方法用于停止 MutationObserver 实例的观察。一旦调用了 disconnect() 方法观察器将不再监听 DOM 变化直到再次调用 observe() 方法重新启动。 示例
// 创建 MutationObserver 实例
const observer new MutationObserver(callback);// 开始观察目标元素
observer.observe(target, config);// 停止观察
observer.disconnect();5. takeRecords()方法 takeRecords() 方法用于获取当前尚未处理的 DOM 变化记录。通常MutationObserver 的回调函数会在触发后处理 DOM 变化记录但在某些情况下我们可能需要在触发回调之前检查未处理的变化记录。 示例
// 创建 MutationObserver 实例
const observer new MutationObserver(callback);// 开始观察目标元素
observer.observe(target, config);// 获取未处理的 DOM 变化记录
const unprocessedRecords observer.takeRecords();// 手动处理未处理的记录
if (unprocessedRecords.length 0) {unprocessedRecords.forEach(record {// 处理未处理的记录});
}使用场景
懒加载可以使用Mutation Observer来监测当元素进入视口时动态加载内容例如图片懒加载。自动保存表单数据可以在表单元素的值发生变化时触发保存操作以避免数据丢失。动态内容更新在单页面应用SPA中可以使用Mutation Observer来监测内容的
总结
MutationObserver固然好用但是其也存在缺点。 首先是性能损耗 虽然在MutationEvent的基础上优化了许多但是监听body的操作对性能影响还是非常大的一切用户操作可能都会使函数频繁的回调。 解决方案尽量限制监听范围只监听必要的节点或限制监听的变化类型以减小回调的频率。其次是操作冲突 由于回调函数非唯一性如果两个观察者监听变化后的操作有依赖关系可能会造成错误或者冲突 解决方案我们可以采用锁的机制确保在满足特定条件时才能执行相关操作以避免冲突和错误。最后是无法在IFrame中监听变化MutationObserver操作是基于当前DOM进行监听的所以无法跨线程与窗口 解决方案使用跨线程和跨窗口通信机制如postMessage来实现监听和数据传递。