当前位置: 首页 > news >正文

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

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`,来实现监听和数据传递。
    

相关文章:

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

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

oracle(19c)用户管理

简介 本文介绍 Oracle 中的用户管理,包含以下内容: 概念介绍 系统用户 解锁 hr 用户 创建用户 用户相关案例 使用 Profile 管理用户口令 Oracle 的认证方式 重置管理员(sys)密码 1. 概念介绍 使用前可以自行安装oracle数据库 oracle19c安装&a…...

浅谈安科瑞智慧用电系统在电气火灾中的应用

摘要:为了对电气火灾事故进行预测和预警,同时为了对电气火灾事故的应急救援提供 支持,将智慧用电监控系统应用于电气火灾中。该系统利用物联网、移动互联网、云平台、大数据技术,实现对电气线路电流、漏电、温度、谐波等参数进行…...

【Material-UI】Button 组件中的尺寸设置(Sizes)详解

文章目录 一、基础尺寸选项1. 小尺寸(Small)2. 中等尺寸(Medium)3. 大尺寸(Large) 二、尺寸的应用场景三、高级用法和最佳实践1. 使用主题调整默认尺寸2. 确保一致性3. 考虑无障碍设计 四、总结 在用户界面…...

Java学习Day20

Vue学习 nodejs的安装与环境配置 1.直接去官网下载合适版本的nodejs( https://nodejs.org/zh-cn/download/prebuilt-installer) 2.解压下载的安装包,将文件路径配置到系统变量的path中,然后确认后退出。可以使用终端来查看安装的nodejs版本。使用winR…...

代理IP怎么弄,如何在电脑中设置IPXProxy代理IP?

随着互联网的不断普及,人们可以利用网络在不同的领域实现更多的可能性。在这个过程中,许多新型网络技术受到人们的关注,代理IP就是其中之一。使用代理IP可以隐藏真实的IP地址,帮助我们突破网络限制、保护隐私、进行网页抓取等一系…...

MacOS 查看端口命令

netstat 命令 查看所有监听的端口 netstat -nat | grep LISTEN 查看9000端口 netstat -nat | grep 9000 # 示例输出 tcp4 0 0 127.0.0.1.9000 *.* LISTEN lsof 命令 查看所有TCP监听的端口 lsof -n -P -i TCP -s TCP:LISTEN 参…...

【python】序列化与反序列化

序列化与反序列化 JSON、CSV和YAML都是常见的数据序列化和反序列化格式。它们都可以用于将数据从一种表示形式转换为另一种表示形式。 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它使用键值对的形式来表示数据&#xff…...

补充:关于GRU的详细运作原理以及特殊的优化思路

1. GRU的基本结构和运作原理 1.1 GRU的基本概念 Gated Recurrent Unit (GRU) 是一种简化版的循环神经网络 (RNN),它通过引入门控机制来解决长期依赖问题,同时减少参数数量以降低计算复杂度。 1.2 GRU的结构详解 GRU 包含两个门控机制:更新门 (update gate) 和重置门 (re…...

xxl-job 源码梳理(2)-服务端

目录 1. 控制面的接口2.手动触发任务2. 定时任务的实现 1. 控制面的接口 服务端包含xxl-job的管理端,页面上的接口后端一系列的controller接口 appName是一个核心概念,它是指执行器应用的名称,appName是执行器的唯一标识 页面上的接口&#…...

C++ GDl+ 多张图片合并生成GIF动画格式图片

使用ImageMagick多张图合成GIF。 1、工具下载安装 下载地址:ImageMagick – Download,windows下载版本如下: 下载后,安装,安装时选择为C/C安装动态库和头文件。 2、代码实现 附加包含目录:ImageMagick-7.…...

【C++】模拟实现list

🦄个人主页:修修修也 🎏所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目及其功能 📌了解list官方标准 了解模拟实现list 📌了解更底层的list实现 二.list迭代器和vector迭代器的异同 📌迭…...

怎么使用git merge合并两个分支?

在Git中,git merge命令用于将两个或多个开发历史(通常指分支)合并到一起。以下是一个基本的步骤指南,说明如何使用git merge来合并两个分支。 ### 前提条件 - 确保你已经安装了Git,并且熟悉基本的Git命令,如…...

ios 5.5寸、ipad13英寸如何截屏

ios上架的时候,你可能会发现,上架需要ios 5.5寸,ipad需要13英寸的屏幕截屏。 但是尴尬了,我们手头上的手机,可能是最新的iphone 15,并没有远古时代iphone 8 plus的5.5寸,那么我们该如何截屏呢&…...

spdlog日志库--输出格式(fmt 库集成)

系列目录 spdlog日志库–基础介绍 spdlog日志库–源码解析 文章目录 1. 格式输出fmt格式输出2. format_spec 格式空间正数和负数的格式#号控制输出格式3. %s占位符 切换 {}占位符 (fmtlib(fmt::format)){}占位符 -> %s等占位符%s占位符 -> {}占位符4. 不使用占位符({}、%…...

Docker简介 MacM1安装Docker

文章目录 1 Docker简介2 Docker VS 虚拟机1 Docker优势2 Docker用途 3 MacM1 下载安装Docker1 配置环境变量 4 配置Docker2 设置Docker资源3 设置Docker镜像 参考 1 Docker简介 Docker主要解决了软件开发和运行配置的问题,但是由于其功能的强大,也被应用…...

【Linux】yum软件包管理器(使用、生态、yum源切换)

目录 1.yum-软件包管理器😸1.1yum使用方法1.2什么是yum?😸1.3yum的周边生态1.4yum源切换1.4.1 查看系统本身yum源1.4.2 软件源1.4.3yum源配置 1.yum-软件包管理器 以下操作需要联网的情况下进行 😸1.1yum使用方法 安装软件时由于需…...

群晖NAS安装Video Station结合内网穿透实现远程访问本地存储的影音文件

文章目录 前言1.使用环境要求:2.下载群晖video station:3.公网访问本地群晖video station:4.公网条件下访问本地群晖video station5.公网条件下使用移动端(安卓,ios等系统)访问本地群晖video station 前言 …...

Vue中@click.stop与@click.prevent

Vue中click.stop与click.prevent 一、click.stop 问题&#xff1a;父元素中添加了一个click事件&#xff0c;其下面的子元素中也添加了click事件&#xff0c;此时&#xff0c;我想点击子元素获取子元素的点击事件&#xff0c;但却触发的是父元素的事件&#xff1a; <view …...

沐风老师3DMax对象随机颜色插件使用方法

3DMax对象随机颜色插件使用教程 3DMax对象颜色插件,是一个功能强大的脚本,它通过提供高级工具来操纵场景中的对象颜色、材质和实例,从而增强了3D设计师和艺术家的工作流程。这个多功能脚本提供了一系列功能,旨在简化对象、组和实例的着色过程。 3DMAX对象颜色插件主要具有…...

《探秘跨网段局域网IP广播:解锁网络通信的新姿势》

一、从基础出发:广播与跨网段 在计算机网络的世界中,广播域是一个至关重要的概念。简单来说,广播域是指网络中能接收任一台主机发出的广播帧的所有主机集合。当一台主机在广播域内发出一个广播帧时,同一广播域内的所有其他主机都可以收到该广播帧。在没有路由器或 VLAN 分割…...

C语言中的数据类型(二)--结构体

在之前我们已经探讨了C语言中的自定义数据类型和数组&#xff0c;链接如下&#xff1a;C语言中的数据类型&#xff08;上&#xff09;_c语言数据类型-CSDN博客 目录 一、结构体的声明 二、结构体变量的定义和初始化 三、结构体成员的访问 3.1 结构体成员的直接访问 3.2 结…...

元器件基础学习笔记——结型场效应晶体管 (JFET)

场效应晶体管&#xff08;Field Effect Transistor&#xff0c;FET&#xff09;简称场效应管&#xff0c;是一种三端子半导体器件&#xff0c;它根据施加到其其中一个端子的电场来控制电流的流动。与双极结型晶体管 &#xff08;BJT&#xff09; 不同&#xff0c;场效应晶体管 …...

.Net Framework 4/C# 属性和方法

一、属性的概述 属性是对实体特征的抽象&#xff0c;用于提供对类或对象的访问&#xff0c;C# 中的属性具有访问器&#xff0c;这些访问器指定在它们的值被读取或写入时需要执行的语句&#xff0c;因此属性提供了一种机制&#xff0c;用于把读取和写入对象的某些特征与一些操作…...

【Python进阶】元类编程

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…...

【LRU】 (最近最少使用)

LRU (最近最少使用) 文章目录 LRU (最近最少使用)一、LRU是什么&#xff1f;二、实现1.常规算法2.双栈更替总结 一、LRU是什么&#xff1f; LRU&#xff08;Least Recently Used&#xff09;是一种常见的缓存淘汰策略&#xff0c;核心思想是 “淘汰最长时间未被使用的缓存数据…...

AI API、AI 聊天助手,两大服务助力应用智能化转型

网络效应、转换成本——这些一度定义了我们这个时代商业逻辑的规则&#xff0c;在 AI 时代迅速崩塌。创新性功能被无差别克隆包围&#xff0c;差异化优势在底层能力翻新中消散…… 更别说那些决策迟缓、行动无法言出法随的“后来者”&#xff0c;注定与市场窗口擦身而过。唯快…...

C++ const 修饰符深入浅出详解

C const 修饰符深入浅出详解 &#x1f4c5; 更新时间&#xff1a;2025年6月6日 &#x1f3f7;️ 标签&#xff1a;C | const关键字 | 常量 | 多文件编程 | 现代C 文章目录 前言&#x1f31f; 一、const 是什么&#xff1f;为什么要用&#xff1f;示例✅ const 的四大好处 &…...

RT-Thread内核组成——内核移植

内核移植就是指将 RT-Thread 内核在不同的芯片架构、不同的板卡上运行起来&#xff0c;能够具备线程管理和调度&#xff0c;内存管理&#xff0c;线程间同步和通信、定时器管理等功能。移植可分为 CPU 架构移植和 BSP&#xff08;Board support package&#xff0c;板级支持包&…...

【C++进阶篇】C++11新特性(下篇)

C函数式编程黑魔法&#xff1a;Lambda与包装器实战全解析 一. lambda表达式1.1 仿函数使用1.2 lambda表达式的语法1.3 lambda表达式使用1.3.1 传值和传引用捕捉1.3.2 隐式捕捉1.3.3 混合捕捉 1.4 lambda表达式原理1.5 lambda优点及建议 二. 包装器2.1 function2.2 bind绑定 三.…...