我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaScript中MutationObServer监听DOM元素举例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaScript中MutationObServer监听DOM元素举例分析

这篇文章主要介绍“JavaScript中MutationObServer监听DOM元素举例分析”,在日常操作中,相信很多人在JavaScript中MutationObServer监听DOM元素举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript中MutationObServer监听DOM元素举例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、基本使用

可以通过MutationObserver构造函数实例化,参数是一个回调函数。

let observer = new MutationObserver(() => console.log("change"));console.log(observer);

observer对象原型链如下:

MutationObserver实例:

JavaScript中MutationObServer监听DOM元素举例分析

可以看到有disconnectobservertakeRecords方法。

1. observer方法监听

observer方法用于关联DOM元素,并根据相关设置进行监听。

语法如下:

// 接收两个参数observer(DOM元素, MutationObserverInit对象);

其中:

  • 第一个参数DOM元素就是页面元素,比如:body、div等。

  • 第二个参数就是设置要监听的范围。比如:属性、文本、子节点等,是一个键值对数组。


示例1,监听body元素class的变化:

let observer = new MutationObserver(() => console.log("change"));// 监听body元素的属性变化observer.observe(document.body, {    attributes: true});// 更改body元素的class,会异步执行创建MutationObserver对象时传入的回调函数document.body.className = "main";console.log("修改了body属性");// 控制台输出://    修改了body属性//    change

上面 change 的输出是在 修改了body属性 之后,可见注册的回调函数是异步执行的,是在后面执行的。

2. 回调函数增加MutationRecord实例数组参数

现在回调函数非常简单,就是输出一个字符串,看不出到底发生了什么变化。

其实回调函数接收一个 MutationRecord 实例数组,实务中可以通过这个查看详细的信息。

let observer = new MutationObserver(    // 回调函数是一个 MutationRecord 实例数组。格式如下:    //     [MutationRecord, MutationRecord, MutationRecord, ...]    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true});document.body.className = "main";console.log("修改了body属性");// 控制台输出://    修改了body属性//     (1) [MutationRecord]

其中 mutationRecords信息 如下:

MutationRecord实例

JavaScript中MutationObServer监听DOM元素举例分析

其中几个比较关键的信息:

  • attributeName 表示修改的属性名称

  • target 修改的目标

  • type 类型

如果多次修改body的属性,那么会有多条记录:

// MutationRecordlet observer = new MutationObserver(    // 回调函数接收一个 MutationRecord 实例,是一个数组。    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true}); // 修改三次document.body.className = "main";document.body.className = "container";document.body.className = "box"; // 控制台打印如下://     (3) [MutationRecord, MutationRecord, MutationRecord]

注意:

这里不是修改一次就执行一次回调,而是每修改一次就往 mutationRecords 参数加入一个 MutationRecord 实例,最后执行一次回调打印出来。

如果修改一次就执行一次回调,那么性能就会比较差。

3. disconnect方法终止回调

如果要终止回调,可以使用disconnect方法。

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true});// 第一次修改document.body.className = "main"; // 终止observer.disconnect(); // 第二次修改document.body.className = "container"; // 没有日志输出

这里没有日志输出,包括第一次修改也没有日志输出,因为回调函数的执行是异步的,是在最后执行的。后面把observer终止了,所以就不会执行了。

可以用setTimeout控制最后才终止,这样回调就会正常执行。

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true});// 第一次修改document.body.className = "main"; // 终止setTimeout(() => {    observer.disconnect();    // 第三次修改,下面修改不会回调了    document.body.className = "container";}, 0); // 第二次修改document.body.className = "container"; // 页面输出://    (2) [MutationRecord, MutationRecord]

终止之后再启用

终止了之后可以再次启动,请看下面示例:

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true});// 第一次修改,会入 mutationRecords 数组document.body.className = "main";// 终止setTimeout(() => {    observer.disconnect();    // 第二次修改,因为终止了,下面修改不会入 mutationRecords 数组    document.body.className = "container";}, 0);setTimeout(() => {    // 再次启用    observer.observe(document.body, {        attributes: true    });    // 修改body属性,会入 mutationRecords 数组    document.body.className = "container";}, 0); // 控制台输出://    [MutationRecord]//    [MutationRecord]

这边回调函数是执行了两次,打印了两个,其中:

  • 第一个输出是在第一次修改,后面没有同步代码了,就执行了回调。

  • 第二个输出是在第三次修改,因为重新启用了,所以就正常执行了回调。

第二次修改,因为observer被终止了,所以修改body的属性不会入 mutationRecords 数组。

4. takeRecords方法获取修改记录

如果希望在终止observer之前,对已有的 mutationRecords 记录进行处理,可以用takeRecords方法获取。

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true}); // 第一次修改,会入 mutationRecords 数组document.body.className = "main";// 第二次修改,会入 mutationRecords 数组document.body.className = "container";// 第三次修改,会入 mutationRecords 数组document.body.className = "box";// 取到修改记录,可以对其进行处理let mutationRecords =  observer.takeRecords();console.log(mutationRecords);// 控制台打印://     (3) [MutationRecord, MutationRecord, MutationRecord]console.log(observer.takeRecords());// 控制台打印://    []// 终止observer.disconnect();

二、监听多个元素

上面监听都是只有一个元素,如果要监听多个元素可以复用MutationObserver实例

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));// 创建 div1 元素,并监听let div1 = document.createElement("div");observer.observe(div1, {    attributes: true});div1.id = "box1"; // 创建div2并监听let div2 = document.createElement("div");observer.observe(div2, {    attributes: true});div2.id = "box2"; // 控制台打印://    (2) [MutationRecord, MutationRecord]

控制台打印了两个MutationRecord,其中:

  • 第一个 MutationRecord 就是 div1 的id属性修改记录。

  • 第二个 MutationRecord 就是 div2 的id属性修改记录。

其他使用方式和上面的类似。

三、监听范围MutationObserverInit对象

上面的监听都是监听属性,当然也可以监听其他的东西,比如:文本、子节点等。

1. 观察属性

上面的例子都是观察元素自有的属性,这里再举一个自定义属性的例子。

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true});// 修改自定义的属性document.body.setAttribute("data-id", 1); // 控制台打印://    [MutationRecord]

修改自定义的属性一样会加入到 mutationRecords 数组。

另外值的一提的是 data-id 经常用来给元素标记一些数据啥的,如果发生变化,程序就可以监听到,就可以处理一些相应的逻辑。

attributeFilter过滤:

如果要监听指定的属性变化,可以用 attributeFilter 过滤。

let observer = new MutationObserver(    (mutationRecords) => console.log(mutationRecords));observer.observe(document.body, {    attributes: true,    // 设置白名单    attributeFilter: ["data-id"]}); // 修改白名单 attributeFilter 内的属性,会入 mutationRecordsdocument.body.setAttribute("data-id", 1); // 修改不在白名单 attributeFilter 内的属性,不会入 mutationRecordsdocument.body.setAttribute("class", "main"); // 控制台打印://    [MutationRecord]

attributeOldValue记录旧值

如果要记录旧值,可以设置 attributeOldValue true

let observer = new MutationObserver(    // MutationRecord对象中oldValue表示旧值    (mutationRecords) => console.log(mutationRecords.map((x) => x.oldValue)));observer.observe(document.body, {    attributes: true,    attributeOldValue: true,});// 第一次修改,因为原来没有值,所以旧值 oldValue = nulldocument.body.setAttribute("class", "main");// 第二次修改,因为前面有改了一次,所以旧值 oldValue = maindocument.body.setAttribute("class", "container"); // 控制台打印://    (2) [null, 'main']

2. 观察文本

观察文本设置 characterDatatrue 即可,不过只能观察文本节点。

请看如下示例:

<!-- 一个性感的div --><div id="box">Hello</div><script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );    // 获取文本节点    let textNode = document.getElementById("box").childNodes[0];    observer.observe(textNode, {        // 观察文本变化        characterData: true    });    // 修改文本    textNode.textContent = "Hi";     // 控制台打印:    //    [MutationRecord]</script>

如果直接监听div元素,那么是不生效的:

<!-- 一个性感的div --><div id="box">Hello</div><script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );    // 监听div不会生效    let box = document.getElementById("box");    observer.observe(box, {        characterData: true    });    box.textContent = "Hi";     // 控制台无输出</script>

characterDataOldValue记录旧值:

如果要记录文本旧值,可以设置 characterDataOldValuetrue

<!-- 一个性感的div --><div id="box">Hello</div> <script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords.map((x) => x.oldValue))    );    // 获取文本节点    let textNode = document.getElementById("box").childNodes[0];    observer.observe(textNode, {        // 观察文本变化        characterData: true,        // 保留旧数据        characterDataOldValue: true,    });    // 修改文本两次    textNode.textContent = "Hi";    textNode.textContent = "Nice";     // 控制台打印:    //    (2) ['Hello', 'Hi']</script>

因为div内的内容原本为Hello,先修改为Hi,又修改为Nice,所以两次修改的旧值就为:Hello 和 Hi 了。

3. 观察子节点

MutationObserver 实例也可以观察目标节点子节点的变化。

<!-- 一个性感的div --><div id="box">Hello</div><script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );    // 获取div    let box = document.getElementById("box");    observer.observe(box, {        // 观察子节点变化        childList: true,    });    // 添加元素    let span = document.createElement("span")    span.textContent = "world";    box.appendChild(span);     // 控制台打印:    //    [MutationRecord]</script>

MutationRecord中的addedNodes属性记录了增加的节点。

移除节点:

<!-- 一个性感的div --><div id="box">Hello</div> <script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );     // 获取div    let box = document.getElementById("box");    observer.observe(box, {        // 观察子节点变化        childList: true,    });    // 移除第一个子节点,就是Hello文本节点    box.removeChild(box.childNodes[0]);     // 控制台打印:    //    [MutationRecord]</script>

MutationRecord中的removedNodes属性记录了移除的节点。

移动节点:

对于已有的节点进行移动,那么会记录两条MutationRecord记录,因为移动现有的节点是先删除,后添加。

<!-- 一个性感的div --><div id="box">Hello<span>world</span></div> <script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );     // 获取div    let box = document.getElementById("box");    observer.observe(box, {        // 观察子节点变化        childList: true,    });    // 将span节点移动到Hello节点前面    box.insertBefore(box.childNodes[1], box.childNodes[0]);    // 移动节点,实际是先删除,后添加。     // 控制台打印:    //    (2) [MutationRecord, MutationRecord]</script>

4. 观察子树

上面观察的节点都是当前设置的目标节点,比如body,就只能观察body元素和其子节点的变化。

如果要观察body及其所有后代节点的变化,那么可以设置subtree属性为true

<!-- 一个性感的div --><div id="box">Hello<span>world</span></div> <script type="text/javascript">    let observer = new MutationObserver(        (mutationRecords) => console.log(mutationRecords)    );     let box = document.getElementById("box");    observer.observe(box, {        attributes: true,        // 观察子树的变化        subtree: true    });    // span元素的id属性变化就可以观察到    box.childNodes[1].id = "text";    // 控制台打印:    //    [MutationRecord]</script>

subtree设置为true后,不光div元素本身,span元素也可以观察到了。

到此,关于“JavaScript中MutationObServer监听DOM元素举例分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaScript中MutationObServer监听DOM元素举例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavaScript中MutationObServer监听DOM元素举例分析

这篇文章主要介绍“JavaScript中MutationObServer监听DOM元素举例分析”,在日常操作中,相信很多人在JavaScript中MutationObServer监听DOM元素举例分析问题上存在疑惑,小编查阅了各式资料,整理
2023-06-21

Javascript中DOM、节点和获取元素的示例分析

这篇文章给大家分享的是有关Javascript中DOM、节点和获取元素的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。DOM文档:DOM中的“D”,当创建一个网页并把它加载到Web浏览器中时,它把编写的网
2023-06-25

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录