DOM – MutationObserver
介绍
它和 IntersectionObserver, ResizeObserver 差不多, 都是观察 element 变化的.
它可以观察元素的 attribute 增加, 移除, 修改, append child 等等.
建议先看前 2 篇 IntersectionObserver 和 ResizeObserver 一起了解会比较容易.
new MutationObserver()
const mo = new MutationObserver((mutations) => {
console.log("mutations", mutations);
});
mo.observe(document.querySelector(".container"), {
attributes: true,
});
调用方式和 Intersection, ResizeObserver 是一样的.
注意: 它和 IO 和 Resize 有个区别, IO, Resize 调用 observe 第一次会马上触发掉, 但 Mutation 没有, 它会等到真的有改变时才触发.
还有一个特别之处是 observe 的时候需要一个 config. 指定要观察的范围.
出于性能考虑, 观察的范围越广性能越伤, 所以请按需设置哦.
观察 attributes
attributes: true
可以观察到元素添加, 移除, 修改 attribute. (注: 只要有 value set 即便 value 是一样的, 它依然会触发哦, 如果不想这样, 我们可以通过 oldValue 来 filter 掉)

attributeOldValue: true

多了一个 oldValue
attributeFilter: ["contenteditable"]
指定要观察的 attribute, 没有在 list 里面的, 添加, 移除, 修改都不会触发.
观察 Child 和 Descendant Element
childList: true
当元素 appendChild / removeChild 的时候触发.
subtree: true
当元素有子孙后裔插入或移除时触发.

观察 TextNode textcontent
characterData: true & characterDataOldValue: true
const textNode = document.createTextNode("Hello World");
mo.observe(textNode, { characterData: true, characterDataOldValue: true });
setTimeout(() => {
textNode.textContent = "SuperMan";
}, 3000);
效果

注意, 一定要是 TextNode 哦.
const p = document.createElement("p");
p.textContent = "Hello World";
mo.observe(p, { characterData: true, characterDataOldValue: true });
setTimeout(() => {
p.textContent = "SuperMan";
document.body.append(p);
}, 3000);
换成 p 就不灵了.

虽然 p 是有效的, 可以 append to body 看到字, 但是 observer 没有监听到它. 所以监听的节点一定要是 TextNode.
触发时机
和 IntersectionObserver,ResizeObserver 不同。
MutationObserver 触发的很早,它类似 Microtask。
而 IntersectionObserver,ResizeObserver 则是 after ui render。
也合理啦,毕竟 MutationObserver callback 获取的资料比如 addedNodes, removedNode 这些都不需要等 ui render。
window.setTimeout(() => {
const container = document.querySelector<HTMLElement>('.container')!;
const mo = new MutationObserver(
records => console.log(records[0].addedNodes.length > 0 ? 'mutation add' : 'mutation remove'), // 2, 4
);
mo.observe(container, { childList: true, subtree: true });
requestAnimationFrame(() => console.log('rAF')); // 6
const h1 = container.querySelector('h1')!;
h1.remove();
console.log('sync'); // 1
queueMicrotask(() => {
console.log('micro1'); // 3
container.appendChild(h1);
queueMicrotask(() => {
console.log('micro2'); // 5
});
});
}, 2000);
效果

相当于,h1.remove 之后它就 queueMicrotask for mutation callback。
没有 unobserve 方法,但有 takeRecords 方法
相关 Issue – Disconnect single target instead of all
不像 IntersectionObserver 和 ResizeObserver 有 unobserve 可以取消指定 element 的监听,
MutationObserver 只有 disconnect 一次性取消所有监听。
workaround 的方案是 wrap 一层,然后自己记入 element,unobserve 时,调用 disconnect 然后在 re-observe 其它的回去。参考高赞回复。
另外 MutationObserver 有一个 takeRecords 方法,这个方法用在 disconnect 之前,因为 MutationObserver 触发是 microtask,
所以在同步执行过程中,如果你 disconnect,这时是有可能已经有一些 MutationRecord 即将要发布的,而这个 takeRecords 方法就可以把它们拿出来处理,然后你才 disconnect。
DOM – MutationObserver的更多相关文章
- HTML5新特性之Mutation Observer
Mutation Observer(变动观察器)是监视DOM变动的接口.当DOM对象树发生任何变动时,Mutation Observer会得到通知. 要概念上,它很接近事件.可以理解为,当DOM发生变 ...
- livequery源码解读
从使用说起: 若干年前,有一天发现,通过js代码创建的html元素及ajax加载的html,无法被$([selector]).click(function(){...})绑定上事件,于是发现了jQue ...
- js实现数据视图双向绑定原理
这个方法了不起啊..vue.js和avalon.js 都是通过它实现双向绑定的..而且Object.observe也被草案发起人撤回了..所以defineProperty更有必要了解一下了几行代码看他 ...
- codepen & js demos
codepen & js demos Mutation Observer & customize resize event listener & demo https://co ...
- window resize & resize observer
window resize & resize observer https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_e ...
- 强大的DOM变化观察者MutationObserver
在这之前 DOM3 提供了 Mutation events 事件 DOMAttrModified DOMAttributeNameChanged DOMCharacterDataModified DO ...
- 使用MutationObserver对象封装一个监听DOM生成的函数
(function(win){ 'use strict'; var listeners = []; var doc = win.document; var MutationObserver = win ...
- JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化
摘要: 掌握MutationObserver. 这是专门探索 JavaScript 及其所构建的组件的系列文章的第10篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工 ...
- js dom 观察者属性 MutationObserver
MDN上说的很清楚 MutationObserver给开发者们提供了一种能在某个范围内的DOM树发生变化时作出适当反应的能力.该API设计用来替换掉在DOM3事件规范中引入的Mutation事件 co ...
- MutationObserver DOM变化的观察
简单的给MutationObserver做个测试及总结笔记. MutationObserver,window上的一个(构造)函数,可以通过其创建的观察者(观察对象)达到观察DOM的变化的效果. 可适用 ...
随机推荐
- Day 1 - 二分
整数二分 我们可以做到每次排除一半的答案,时间复杂度 \(O(\log n)\). long long l = L, r = R; while(l <= r) { long long mid = ...
- 七天.NET 8操作SQLite入门到实战 - 第七天Blazor学生管理页面编写和接口对接(3)
前言 本章节我们的主要内容是完善Blazor学生管理页面的编写和接口对接. 七天.NET 8 操作 SQLite 入门到实战详细教程 第一天 SQLite 简介 第二天 在 Windows 上配置 S ...
- pidstat命令详解
pidstat命令详解 pidstat 命令是 sysstat 工具的一个命令,用来监控全部或者指定进程的CPU.内存.线程.设备IO等系统资源的占用情况.pidstat 首次运行时显示自系统启动开始 ...
- python面向对象:多态
python面向对象:多态 多态的应用场景 1. 对象所属的类之间没有继承关系 调用同一个函数fly(), 传入不同的参数(对象),可以达成不同的功能 class Duck(object): # 鸭子 ...
- python面向对象游戏练习:好人坏人手枪手榴弹
python面向对象游戏练习:好人坏人手枪手榴弹 主要是多态的练习,对象作为参数传给方法使用 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 ...
- openeuler linux内核4.19安装(centos 同理)
linux内核安装: 安装内核步骤 下载相应内核版本[我这里用的是linux-4.19.90.tar.gz] 下载网址:https://mirrors.edge.kernel.org/pub/linu ...
- 【Mybatis + Spring】 Mybatis - Spring 结合
环境搭建 EvBuild 软件环境准备 - MySQL 5.0 + - IDEA 2018 + - JDK1.8 + 依赖包相关 - Junit单元测试 - JDBC驱动 - Mybatis 组件 - ...
- (续)signal-slot:python版本的多进程通信的信号与槽机制(编程模式)的库(library) —— 强化学习ppo算法库sample-factory的多进程包装器,实现类似Qt的多进程编程模式(信号与槽机制) —— python3.12版本下成功通过测试
前文: signal-slot:python版本的多进程通信的信号与槽机制(编程模式)的库(library) -- 强化学习ppo算法库sample-factory的多进程包装器,实现类似Qt的多进程 ...
- GPG公钥的删除与注销
参考: 如何在 Gitee 上使用 GPG 我们通过在本地主机保存GPG私钥,然后在Gitee或Github上保存GPG公钥的方式来实现对git的commit和tag操作的签名. 当GPG公私秘钥对作 ...
- 国产操作系统 deepin —— UOS 系统下使用蓝牙音箱或蓝牙耳机不能正常工作
近日搞来了一个国产CPU的电脑,自带系统为UOS,具体可见: https://www.cnblogs.com/devilmaycry812839668/p/14828130.html 忽然发现这个系统 ...