“Mutation Observer:让DOM变化尽在掌握

news2024/9/25 3:19:48

Mutation Observer(变动观察者)

定义

Mutation Observer是一种JavaScript API,用于异步监测DOM树的变动,包括元素的添加、删除、属性变化等。当DOM发生变动时,它可以触发回调函数,允许你对变动作出响应。

Mutation Observer的意义

Mutation Observer API 的设计意义就是用来替换掉在 DOM 3 事件规范中引入的 Mutation events。

你可能会问了为什么呢?

这就要讲讲Mutation events了
先给大家看一Mutation events的简单用法

jcode

上面这段代码乍一看可能没什么问题,确实也能实现监听改变的功能,但是往深层次考虑它还是存在很多缺点。例如:

  1. 兼容性问题

    • IE9 不支持 Mutation Events:Mutation Events在较旧版本的Internet Explorer(如IE9及更早版本)中不受支持。这意味着如果我们使用IE9的浏览器运行这段代码,将会失效。
    • Webkit 内核不支持 DOMAttrModified:Webkit内核浏览器(如旧版本的Safari和Chrome)不支持DOMAttrModified属性的Mutation Event。
    • Firefox 不支持 DOMElementNameChanged 和 DOMAttributeNameChanged:Mozilla Firefox不支持DOMElementNameChangedDOMAttributeNameChanged这两种Mutation Event。
  2. 性能问题

    • 同步执行:Mutation Events是同步执行的,它们会在DOM发生变化时立即触发,从事件队列中取出事件,执行事件处理程序,然后从队列中移除。如果DOM变化频繁,每次事件都需要执行这些操作,如果产生堵塞,将会引起全局堵塞
    • 事件冒泡:Mutation Events使用事件冒泡来传播事件。如果在事件冒泡过程中触发其他Mutation Events,可能会导致事件处理程序的嵌套,这可能会占用大量的JavaScript执行时间,甚至导致浏览器线程阻塞。

Mutation Observer的出现就是为了代替Mutation events,来弥补Mutation events的缺陷。而且Mutation Events能监听的DOM树结构变化,Mutation Observer都能监听。

  1. DOMAttrModified:当元素的属性被修改时触发,我们可以捕获属性值的更改。
  2. DOMAttributeNameChanged:当元素的属性节点名称发生变化时触发,可以检测到属性名称的修改。
  3. DOMCharacterDataModified:当文本节点的内容发生变化时触发,用于监视文本节点中的文本内容变化。
  4. DOMElementNameChanged:当元素的节点名称发生变化时触发,用于检测节点名称的修改。
  5. DOMNodeInserted:当元素的子节点被插入到DOM树中时触发,我们可以监测到新节点的添加。
  6. DOMNodeRemoved:当元素的子节点被从DOM树中移除时触发,用于检测节点的移除。
  7. DOMNodeInsertedIntoDocument:当元素的子节点被插入到文档中时触发,用于监视节点的插入操作。
  8. DOMSubtreeModified:当DOM树的子树结构发生变化时触发,我们可以捕获到更广泛的DOM树变化。

Mutation Observer的优点

兼容性好

image.png

  1. 实时监测DOM变动:可以实时监测DOM树的变动,而不需要轮询或事件监听器。
  2. 灵活性:可以精确地指定要观察的DOM元素,以及要观察的变动类型。
  3. 性能优好:它通过异步执行回调函数来处理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变动时被触发,它接受两个参数:mutationsListobserver

  • mutationsList:是一个Mutation Record对象的数组,每个对象描述一个DOM变动。
  • observer:对观察器本身的引用。

MutationRecord 对象包含了以下属性:

  1. type:一个字符串,表示变化的类型,可能是 "attributes"(属性更改)、"childList"(子元素的添加或移除)或 "characterData"(文本节点的更改)。
  2. target:变化发生的目标元素。
  3. addedNodes:一个 NodeList 对象,包含了被添加的节点。仅当变化类型为 "childList" 时才存在。
  4. removedNodes:一个 NodeList 对象,包含了被移除的节点。仅当变化类型为 "childList" 时才存在。
  5. previousSibling:变化前目标节点的前一个同级节点。仅当变化类型为 "childList" 时才存在。
  6. nextSibling:变化前目标节点的下一个同级节点。仅当变化类型为 "childList" 时才存在。
  7. attributeName:发生属性更改时的属性名称。仅当变化类型为 "attributes" 时才存在。
  8. oldValue:属性更改前的旧值。仅当变化类型为 "attributes" 时才存在。
  9. 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`,来实现监听和数据传递。
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu14.04安装网卡驱动

1,lspci 查看网卡型号 2,到官网下载解压,进入文件目录 3,新装的服务器会报错,提示我们没有安装make,下载缺少的gcc和make依赖,记得先执执行一下系统更新 sudo apt update && sudo apt upgrade -y sudo apt …

【css】使用CSS绘制奥运五环--巴黎奥运

使用CSS绘制奥运五环 在2024年巴黎奥运会期间,本文来使用 CSS 来画一个奥运五环。奥运五环由五个相互交叠的圆环组成,分别代表五大洲。 奥运五环是相互连接的,因此在视觉上会产生重叠效果,这也是实现五环最有挑战性的部分 HTML结…

Linux -软件包管理 下载与安装方式

1. wget下载 先下载再安装 wget命令是Linux系统用于从Web下载文件的命令行工具,支持 HTTP、HTTPS及FTP协议下载文件 当然现在更多支持用yum工具的,不过有的时候一些镜像站点不再维护一些旧版本的软件时,这时候就可以用wget可以先获取&…

Unity补完计划 之 SpriteEditer Multiple

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正 1. SpriteEditer Multiple Automatic slicing - Unity 手册 这是用于裁剪图集的模式 应用之后精灵编辑器会看到Slice亮…

CSP-J 复赛 模拟题7 and 解析

1.超级素数: 题目描述 素数,又称质数,是指除 11 和其自身之外,没有其他约数的正整数。例如 2,3,5,132,3,5,13 都是素数,而 4,9,12,184,9,12,18 则不是。特别地,规定 11 不是素数(因此自然数的…

【C++进阶学习】第十二弹——C++ 异常处理:深入解析与实践应用

前言: 在C编程语言中,异常处理是一种重要的机制,它允许程序员在运行时捕获和处理错误或异常情况。本文将详细介绍C异常处理的相关知识点,包括异常的定义、抛出与捕获、异常处理的原则、以及在实际编程中的应用。 目录 1. 异常处理…

算法力扣刷题记录 六十九【动态规划基础及509. 斐波那契数】

前言 调整一下做题顺序,多个章节同步进行,穿插练习。可以在各章节的专栏中找同一类。 记录 六十九【动态规划基础】。 一、动态规划理论基础学习 参考学习链接 二、509. 斐波那契数 2.1 题目阅读 斐波那契数 (通常用 F(n) 表示&#x…

屏蔽浏览器搜索出csdn相关内容的方法

屏蔽csdn搜索结果的方法 前言 鉴于你对知识质量的渴望,以及对挖掘知识金子的欲求,你一定想在浏览器结果中去除有关Csdn的全部内容😈**(确信)**,但是当你在用bing或者google搜索有没有可以屏蔽CSDN搜索结果的方法时,通…

一套基于tailwindcss的后台管理系统模板Chakra UI + React + TS

下载地址给你们: https://horizon-ui.com/#version

算法混合杂项

基础类型 可用template 投影 是有方向的 求俩直线交点 推公式 q我们不知道,已知p1 p2,正弦定理,α可以用叉积表示出来 β同理 所以我们能求出p1q 已知piq 回归到我们上一个问题,已知方向和长度,我们就能够求出Voq …

24/8/8算法笔记 不同分类算法的差异

import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.linear_model import LogisticRegression from sklearn.svm import SVCfrom sklearn import datasets 加载数据 我们加载的是啤酒的数据 wine datasets.load_wine() wine LR逻辑斯蒂回归…

【数据结构】数组复习-二分查找法

写这篇博客的起因: 刚开始刷力扣,发现没有一个很好的做题方法,在网络上发现了这个博主的评论,如下。感觉挺适合我,所以开始复习一下数据结构。 c基础主要是看: 1.bilibili上青岛大学王卓第02周03--2.3线…

算法 二

求中点 LR,可能溢出 除以2,等同于右移一位 递归、递归的时间复杂度 母问题的规模 子问题的规模,且都相等 调用次数 不用展开看,就看一层。 归并排序 时间复杂度降低的原因:没有浪费比较。比如选择排序&#xff…

48天笔试训练错题——day44

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 单词倒排 选择题 1. A 类 IP 地址:0.0.0.0 ~ 127.255.255.255 1 字节网络号,3 字节主机号 B 类 IP 地址:128.0.0.0 ~ 191.255.255.255 2…

服务器网络磁盘挂载

一、Ping测试 先测试磁盘网络的连通性 例如:这里申请的网络磁盘是: 127.0.0.1:/shareData ping 127.0.0.1二、挂载 确认连通后,确定需要挂载的目录,这里服务器的挂载目录为:/data/share (自主选择创建目录…

【食物链】

题目 代码 #include<bits/stdc.h> using namespace std; const int N 5e410; int n, k; int p[N], d[N]; int find(int x) {if(p[x] ! x){int root find(p[x]);d[x] d[p[x]];p[x] root;}return p[x]; } int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)…

RaiDrive / Cyberduck 的安装破解

安装完成后&#xff0c;使用方法可以去这里看&#xff1a; Synology DS920 【外网访问】 这篇文章主要是为了解决 RaiDrive 的登录付费和 Cyberduck 的语言 所以可以尽管下载&#xff0c;盘中 RaiDrive 的免登录免费和 Cyberduck 的中文语言是没有问题的 硬盘映射程序 提…

专题 | IAM业界热度不减,2024市场持续井喷(一)

面对无边界、无规则、无差别&#xff08;企业规模&#xff09;的攻防时代&#xff0c;身份安全在网络安全的重要性日益增强。 身份安全是Gartner最近几年来频繁提及的重要未来趋势之一。RSAC 2023上RSA CEO Rohit Ghai 甚至发表了主题为《迫在眉睫的身份危机&#xff09;》的开…

DAMA学习笔记(十二)-数据质量

1.引言 数据管理能力包括为各类应用设计数据模型、安全存储和访问数据、适当地共享数据、从数据中获得知识&#xff0c;以及保障满足业务需求的能力等。但实现数据价值的前提是数据本身是可靠和可信的&#xff0c;换句话说&#xff0c;数据应是高质量的。 导致低质量数据产生的…

聚焦光热型太阳光模拟器助力多晶硅均匀加热

晶圆均匀加热技术综述 晶圆均匀加热是半导体制造过程中的关键技术之一&#xff0c;直接影响着晶圆上各种加工工艺的质量和稳定性。晶圆加热的目的在于化学气相沉积、退火、氧化等工艺中&#xff0c;通过对晶圆进行必要的热处理&#xff0c;以促进或优化后续工艺步骤。不均匀的…