Mutation Observer API 详解

简介: Mutation Observer 提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。

MDN 对Mutation Observer 的描述如下:

Mutation Observer 提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。

换言之,这就是一个 DOM元素变化的监听器,当被观察的目标 DOM 发生改变时就可以执行指定的逻辑。

首先我们可以看一下Mutation Observer的结构

1682518075(1).png

MutationObserver是一个构造函数,他的实例会有 disconnect、observe和 takeRecords 三个方法


constructor


构造函数接收一个函数,用于在 DOM 变化时执行,该函数有两个参数一个是描述所有被触发改动的 MutationRecord 对象数组,另一个是调用该函数的 MutationObserver 对象

function DOMHandler(mutationList, observer) {
  mutationList.forEach((mutation) => {
    switch(mutation.type) {
      case 'childList':
        // 从树上添加或移除一个或更多的子节点
        console.log('结点变更')
        break;
      case 'attributes':
        // mutation.target 中某节点的一个属性值被更改
        console.log('属性变更')
        break;
    }
  });
}
const observer = new MutationObserver(DOMHandler)
复制代码


observe


mutationObserver.observe(target[, options])

  • target: DOM 树中的一个要观察变化的 DOM Node (可能是一个 Element),或者是被观察的子节点树的根节点。
  • options: 一个可选的MutationObserverInit 对象,此对象的配置项描述了 DOM 的哪些变化应该提供给当前观察者的 callback(MDN 说是可选,但是在 chrome 控制台执行时报错必须有至少一个配置项)。
const node1 = document.getElementById('box')
observer.observe(node1, {attributes: true})
node1.setAttribute('name', '张三')
复制代码

然后我们来在元素面板给node1 添加一个属性,此时属性变更触发了回调

1682518095(1).png


disconnect


阻止 MutationObserver 实例继续接收的通知,直到再次调用其 observe() 方法,该观察者对象包含的回调函数都不会再被调用。

observer.disconnect()
node1.setAttribute('name', 'king')
复制代码

调用之后再元素版本修改属性都不会再次触发之前的回调


takeRecords


返回已检测到但尚未由观察者的回调函数处理的所有匹配 DOM 更改的列表,使变更队列保持为空。

observer.observe(node, {attributes: true})
node.setAttribute('name', 'king')
const notices = observer.takeRecords()
复制代码

1682518123(1).png

由此可以看出,DOM 变化之后并不是立即通知执行回调,而是等主线程代码执行完毕再通知,所以 takeRecords 可以将通知提前拦截。

附:observe可接受的 options

属性 说明 默认值
attributes 设为 true 以观察受监视元素的属性值变更。 默认值为 false。
attributeFilter 要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知。 无默认值。
characterData 设为 true 以监视指定目标节点或子节点树中节点所包含的字符数据的变化。 无默认值
childList 设为 true 以监视目标节点(如果 subtree 为 true,则包含子孙节点)添加或删除新的子节点。 默认值为 false。
subtree 的其他值也会作用于此子树下的所有节点,而不仅仅只作用于目标节点。 默认值为 false。


应用场景


Mutation Observer 主要用在需要监听用户是否违规操作 DOM 的场景, 以水印为例, 监听用户是否私自把页面的水印 DOM 进行删除, 如果触发了事件则对水印进行复原

首先创建一个带有水印的页面,生成水印的代码比较长,就不贴在这里了,有需要的可以联系我私发

1682518147(1).png

框选出来的元素就是水印的容器,如果删除掉这个 DOM 元素我们的水印就会被清除

1682518164(1).png

如果用户有一定的网页知识就会打开 F12 通过开发者工具来删除水印,那么我们的工作就白做了,这时候就可以使用Mutation Observer来监听 DOM 的操作了。

window.onload = function () {
  loadMark(settings); // 加载水印
  function DOMHandler(mutationList, observer) {
    mutationList.forEach((mutation) => {
      const { target, nextSibling, removedNodes } = mutation;
      if (mutation.removedNodes.length) { // 如果列表不为空说明触发操作的动作是删除
        if (nextSibling) { // 如果存在下一个相邻子节点执行插入
          console.log('恢复被删除的节点');
          target.insertBefore(removedNodes[0], nextSibling)
        } else { // 直接添加到 target 的末尾
          target.appendChild(removedNodes[0])
        }
      }
    });
  }
  const observer = new MutationObserver(DOMHandler)
  const node = document.body
  observer.observe(node, { attributes: true, childList: true, subtree: true })
};
复制代码

我们在加载完水印之后创建了一个监听器,并且监听了 body 元素(因为我们的水印元素是 body 的直接子元素,如果直接监听刚才的水印元素,删除这个元素并不会触发监听器)。

首先根据 mutation 的 removedNodes字段判断是否进行了删除操作,如果是删除操作再根据是否有下一个相邻节点来判断节点恢复的位置,如果存在相邻节点就在其前面插入被删除的节点,否则直接在末位追加。

实现的效果如下

相关文章
|
9月前
|
JavaScript API
MutationObserver API
MutationObserver API
40 0
|
JavaScript 前端开发 API
45、Mutation Observer API
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
225 0
|
13小时前
|
监控 供应链 搜索推荐
数据驱动电商:深度利用淘宝API接口掌握商品详情
本文探讨了如何利用淘宝API接口获取商品详情数据以助力电商决策。通过API,商家能获取商品标题、价格、库存等信息,从而进行市场分析、库存优化、定价策略制定及个性化推荐。步骤包括注册获取API权限、理解文档、构建数据收集流程、处理分析数据以及应用结果。示例代码展示了如何用Python调用API获取商品详情。善用API和数据驱动策略可在电商市场中取得优势。请注意遵循淘宝的API使用规范。
|
1天前
|
JSON 测试技术 API
API接口测试指南:确保接口稳定性与可靠性的实践
API接口测试是确保软件产品质量的重要组成部分。通过遵循本指南中的测试步骤和最佳实践,开发者可以有效地验证API的功能、性能和安全性,从而提升软件的整体质量和用户满意度。
|
1天前
|
人工智能 自然语言处理 API
利用Python调用KimiGPT API接口
Kimi作为国内目前广受欢迎的AI工具,因其出色的性能和智能功能,迅速赢得了大量用户的青睐。随着用户量的激增,系统在高峰时段可能会面临响应压力。正是借助这一热潮,Kimi团队适时推出了其API服务,使用户和开发者能够更加灵活和深入地集成和使用Kimi的智能功能。
|
2天前
|
前端开发 测试技术 API
vite项目怎么build打包成不同环境的代码?从而适配不同环境api接口
vite项目怎么build打包成不同环境的代码?从而适配不同环境api接口
9 0
|
2天前
|
JavaScript 前端开发 API
详解JS的URL()和URLSearchParams() API接口
详解JS的URL()和URLSearchParams() API接口
8 2
|
2天前
|
API 网络架构 数据格式
API接口详解及其在电子商务中的应用研究
本文介绍了API接口在电子商务中的重要性,详细阐述了API的定义、分类(RESTful, SOAP, GraphQL)和设计原则。通过实例展示了API如何促进数据交换和系统集成,如商品信息共享、订单自动化处理。同时,讨论了API安全性措施,并提供了一个Python代码示例来演示如何获取电商平台的商品信息。API在电子商务领域的应用对于提升业务效率和推动行业创新具有显著影响。
|
9天前
|
监控 数据挖掘 API
京东商品API接口:电商数据自动化的钥匙
京东商品API接口为电商领域带来了巨大的便利和潜力。通过本篇文章,读者应该能够了解如何使用京东商品API接口,并通过示例代码学习如何实际调用API获取商品数据。 随着技术的不断发展,京东商品API接口将继续为电商自动化、数据分析和市场研究提供支持,帮助商家和开发者在竞争激烈的市场中保持领先。我们鼓励读者继续探索和学习,充分利用京东商品API接口带来的机遇。
|
19天前
|
监控 安全 数据挖掘
Email 接口API有哪些?具体分析一下阿里云和AOK的优点
本文介绍了常见的Email接口API,如阿里云邮件推送、AOKSend、SendGrid、Mailgun和Amazon SES。阿里云API以其高稳定性和数据分析功能脱颖而出,支持批量发送和多语言;而AOKSend API以易于集成、高安全性和优秀客户支持为亮点。企业在选择时应考虑自身需求和预算,以优化邮件营销效果。