返回顶部
首页 > 资讯 > 精选 >JavaScript中MutationObServer监听DOM元素举例分析
  • 838
分享到

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

2023-06-21 20:06:16 838人浏览 薄情痞子
摘要

这篇文章主要介绍“javascript中MutationObServer监听DOM元素举例分析”,在日常操作中,相信很多人在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元素举例分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: JavaScript中MutationObServer监听DOM元素举例分析

本文链接: https://lsjlt.com/news/300418.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaScript中MutationObServer监听DOM元素举例分析
    这篇文章主要介绍“JavaScript中MutationObServer监听DOM元素举例分析”,在日常操作中,相信很多人在JavaScript中MutationObServer监听DOM元素举例分析问题上存在疑惑,小编查阅了各式资料,整理...
    99+
    2023-06-21
  • JavaScript中MutationObServer监听DOM元素详情
    一、基本使用 可以通过MutationObserver构造函数实例化,参数是一个回调函数。 let observer = new MutationObserver(() =>...
    99+
    2024-04-02
  • JavaScript如何动态监听DOM元素高度详解
    背景 考虑这样一种情况,产品同学希望达到以下功能: 在我们的网页中有一个固定区域,这个区域会用于渲染从后端拉取的含有图片等资源的富文本字符串。 他需要在内容不超过一个最大高度的时候完...
    99+
    2024-04-02
  • JavaScript DOM元素常见操作的示例分析
    这篇文章主要介绍JavaScript DOM元素常见操作的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:DOM概念DOM(Document Object Model...
    99+
    2024-04-02
  • Javascript中DOM、节点和获取元素的示例分析
    这篇文章给大家分享的是有关Javascript中DOM、节点和获取元素的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。DOM文档:DOM中的“D”,当创建一个网页并把它加载到Web浏览器中时,它把编写的网...
    99+
    2023-06-25
  • JavaScript的事件监听实例分析
    这篇文章主要介绍了JavaScript的事件监听实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript的事件监听实例分析文章都会有所收获,下面我们一起来看看吧。1.什么是事件监听 ?事件监听...
    99+
    2023-06-29
  • JavaScript中HTML元素操作的示例分析
    小编给大家分享一下JavaScript中HTML元素操作的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、获取操作的元...
    99+
    2024-04-02
  • Javascript中DOM范围的示例分析
    这篇文章主要介绍Javascript中DOM范围的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!创建范围Document类型中定义了createRange()方法。在兼容DO...
    99+
    2024-04-02
  • JavaScript中的DOM与BOM实例分析
    这篇文章主要介绍“JavaScript中的DOM与BOM实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript中的DOM与BOM实例分析”文章能...
    99+
    2024-04-02
  • JavaScript中ECMAScript、BOM、DOM的示例分析
    小编给大家分享一下JavaScript中ECMAScript、BOM、DOM的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下...
    99+
    2024-04-02
  • JavaScript中DOM操作的示例分析
    这篇文章主要介绍JavaScript中DOM操作的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:一、DOM概念1. "D":Docment,指的...
    99+
    2024-04-02
  • JavaScript中DOM事件的示例分析
    这篇文章主要介绍了JavaScript中DOM事件的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、事件对象【获取事件对象】什么是事件对象:是个对象,这个对象里有事...
    99+
    2023-06-29
  • javascript中事件监听与事件委托的示例分析
    这篇文章主要介绍了javascript中事件监听与事件委托的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。事件监听与事件委托在js中...
    99+
    2024-04-02
  • javascript组合按键事件监听的示例分析
    这篇文章主要为大家展示了“javascript组合按键事件监听的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“javascript组合按键事件监听的示例...
    99+
    2024-04-02
  • HTML5中的aside元素与article元素的示例分析
    本篇文章为大家展示了HTML5中的aside元素与article元素的示例分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。<aside>元素HTML&...
    99+
    2024-04-02
  • HTML 5本地存储的兼容性与存储监听举例分析
    本篇内容介绍了“HTML 5本地存储的兼容性与存储监听举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • 前端JavaScript多数元素的算法实例分析
    这篇文章主要介绍“前端JavaScript多数元素的算法实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“前端JavaScript多数元素的算法实例分析”文章能帮助大家解决问题。题目:多数元素给...
    99+
    2023-07-02
  • JavaScript中DOM操作常用事件实例分析
    这篇文章主要讲解了“JavaScript中DOM操作常用事件实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript中DOM操作常用事件实例分析”吧!由此可以看出事件分三个...
    99+
    2023-06-30
  • JavaScript中模仿C#编码方式举例分析
    本篇内容介绍了“JavaScript中模仿C#编码方式举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • css中子元素从父元素继承属性的示例分析
    这篇文章主要介绍了css中子元素从父元素继承属性的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 秉持及其标题问题 按照 CSS...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作