• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

JS随笔监听DOM内容改变

武飞扬头像
青青的博客
帮助1

目录

前言

一、addEventListener

        1.示例

二、MutationObserver

1.示例1

2.示例2

总结

参考资料



前言

  今天项目遇到一个需要监听DOM变化,根据DOM的变化情况,来展示不同的内容,于是上网搜索了各种方式,做一下总结,方便下次查看。


一、addEventListener

关于这个API不要查看菜鸟教程中的解释,直接看MDN即可

  1. addEventListener函数说明 :https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener
  2. addEventListener事件参考:事件参考 | MDN

1.示例

对于DOMNodeInserted事件,我们只需要知道使用函数document.addEventListener传递第一个参数为字符串DOMNodeInserted,第二个参数为事件处理函数。

事件处理函数的第一个参数为事件对象,其中属性target为被插入的对象,根据该对象的各种属性,我们执行我们的各种操作(禁用、删除、增加等等)。
代码如下:

  1.  
    <body>
  2.  
    <table id="outside">
  3.  
    <tr>
  4.  
    <td id="t1">one</td>
  5.  
    </tr>
  6.  
    <tr>
  7.  
    <td id="t2">two</td>
  8.  
    </tr>
  9.  
    </table>
  10.  
    <script>
  11.  
    // 改变 t2 的函数
  12.  
    function modifyText() {
  13.  
    var t2 = document.getElementById("t2");
  14.  
    if (t2.firstChild.nodeValue == "three") {
  15.  
    t2.firstChild.nodeValue = "two";
  16.  
    } else {
  17.  
    t2.firstChild.nodeValue = "three";
  18.  
    }
  19.  
    }
  20.  
    // 为 table 添加事件监听器
  21.  
    var el = document.getElementById("outside");
  22.  
    el.addEventListener("click", modifyText, false);
  23.  
    </script>
  24.  
    </body>
学新通

二、MutationObserver

参考文档MDN MutationObserver - Web API 接口参考 | MDN

基础核心:

  • MutationAbserver
  • MutationAbserverInit
    • attributes: true 【是否监听属性变化】
    • attributeFilter: ['popkey'] | undefined 【监听的属性范围,如果设置为undefined | 没有设置表示监听全部的属性】
    • attibuteOldValue: true 【是否把 回调函数中的MutationRecord.oldValue 对象是否包含了更改前的数据
    • characterData: true 【是否监听 内部子文本节点的数据发生变化】
    • characterDataOldValue: true 【是否把 之前的数据发送给 MutationRrecord】
    • childList: true,【是否 监听子节点的插入/删除】
    • subtree: true 【是否 把监听的范围扩展到内部的全部子孙节点】
  • MutationRecor

        

1.示例1

代码如下:

  1.  
    <body>
  2.  
    <div id="test"></div>
  3.  
    <script>
  4.  
    const targetNode = document.getElementById('test');
  5.  
    // 观察器的配置(需要观察什么变动)
  6.  
    const config = { attributes: true, childList: true, subtree: true };
  7.  
    // 当观察到变动时执行的回调函数
  8.  
    const callback = function (mutationsList, observer) {
  9.  
    for (let mutation of mutationsList) {
  10.  
    if (mutation.type === 'childList') {
  11.  
    console.log('有节点发生改变,当前节点的内容是:');
  12.  
    console.log(item.target.innerHTML);
  13.  
    }
  14.  
    else if (mutation.type === 'attributes') {
  15.  
    console.log('修改了' item.attributeName '属性');
  16.  
    }
  17.  
    }
  18.  
    };
  19.  
    // 创建一个观察器实例并传入回调函数
  20.  
    const observer = new MutationObserver(callback);
  21.  
    // 以上述配置开始观察目标节点
  22.  
    observer.observe(targetNode, config);
  23.  
    // 之后,可停止观察
  24.  
    // observer.disconnect();
  25.  
    </script>
  26.  
    </body>
学新通

效果如下图所示:

学新通

2.示例2

  1.  
    <html lang="en">
  2.  
    <head>
  3.  
    <meta charset="UTF-8">
  4.  
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
  5.  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.  
    <title>mutationObserver</title>
  7.  
    </head>
  8.  
    <body>
  9.  
    <div class='parent'>
  10.  
    原始文本
  11.  
    </div>
  12.  
     
  13.  
    <script type="text/javascript">
  14.  
     
  15.  
    const el_class_parent = document.querySelector('.parent');
  16.  
    const el_div = document.createElement('div')
  17.  
    // 文本节点的data就是文本的内容
  18.  
    const node_text = el_class_parent.childNodes[0]
  19.  
     
  20.  
    // observer 观察者
  21.  
    // 创建一个观察者
  22.  
    const observer = new MutationObserver(callback)
  23.  
    // 事件处理器
  24.  
    function callback(mutationRecords, observer){
  25.  
    mutationRecords.forEach(mutationRecord => {
  26.  
    console.dir(mutationRecord)
  27.  
    if(mutationRecord.type === "attributes") return console.log('属性发生了变化 target =', mutationRecord.target)
  28.  
    if(mutationRecord.type === 'childList') return console.log('添加or删除了 childList: ',mutationRecord.target)
  29.  
    if(mutationRecord.type === 'characterData') return console.log('文本节点的数据发生了变化',mutationRecord.target)
  30.  
    })
  31.  
    }
  32.  
     
  33.  
    /*
  34.  
    * 配置文件
  35.  
    */
  36.  
    const config = {
  37.  
    attributes: true,
  38.  
    attributeFilter: undefined, /*需要监听的属性名称列表,如果没有表示监听全部的属性*/
  39.  
    attributeOldValue: true, /*传递之前旧的值给mutationRecord*/
  40.  
    characterData: true, /*是否监听内部文本节点的数据变化*/
  41.  
    characterDataOldValue: true, /*mutationRecord 是否包含内部文本节点变化前的数据*/
  42.  
    childList: true,
  43.  
    subtree: true /*是否把监听的方位放到节点树中的全部子节点上*/
  44.  
    }
  45.  
     
  46.  
    observer.observe(el_class_parent, config)
  47.  
     
  48.  
    // 监听内部文本节点的数据变化characterData
  49.  
    setTimeout(() => {
  50.  
    node_text.data = 'aaa'
  51.  
    }, 0)
  52.  
     
  53.  
    // 如果在一个事件循环内设置多个变化
  54.  
    // 会在callback中接受到多个 mutationRecord
  55.  
    setTimeout(() => {
  56.  
    Promise
  57.  
    .resolve()
  58.  
    .then(() => {
  59.  
    console.log('-------------promise 队列执行')
  60.  
    el_class_parent.setAttribute('path', "promise")
  61.  
    })
  62.  
     
  63.  
    // 设置属性发生变化
  64.  
    el_class_parent.setAttribute('path', 'old-path');
  65.  
    el_class_parent.setAttribute('path', 'new-path')
  66.  
     
  67.  
    // 设置内容发生变化
  68.  
    el_class_parent.innerText = "aaa"
  69.  
     
  70.  
    // 每一次的设置都会调用 callback
  71.  
    el_class_parent.append(el_div)
  72.  
     
  73.  
    console.error('----------------------设置更改完毕')
  74.  
     
  75.  
    setTimeout(() => {
  76.  
    console.log('--------------------------------下一次事件循环')
  77.  
    el_class_parent.setAttribute('path', 'new-path-2')
  78.  
    },0)
  79.  
     
  80.  
    setTimeout(() => {
  81.  
    console.log('--------------------------- 下一次事件循环')
  82.  
    el_div.setAttribute('path', 'div-path')
  83.  
    }, 0)
  84.  
     
  85.  
    }, 1000)
  86.  
    </script>
  87.  
    </body>
  88.  
    </html>
学新通

总结

addEventListener是W3C的API,历史遗留接口,很多问题,整体来说不推荐使用

MutationObserver是H5的API,从设计和兼容性上都要好的多,如果在开发中,使用该api更合适。

DOM MutationObserver在不影响浏览器性能的状态下响应DOM更改

等待全部脚本任务执行完成后,才会运行,即采用异步方式

不过在Chrome测试中发现,addEventListener有些状态监控不到,MutationObserver可以弥补这种情况。而MutationObserver像是消息队列的实现方式,不能查看运行时堆栈。所以开发过程中根据需要使用不同的api,也可以同时使用两套api达到目的。

参考资料

javascript 监听DOM内容改变事件 https://juejin.cn/post/7025877062430752775
书籍《JavaScript框架设计》https://book.douban.com/subject/27133542/
Chrome设置断点的各种姿势 https://cloud.tencent.com/developer/article/1093731
参考文章:https://blog.csdn.net/kinghzking/article/details/123684377

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbcjke
系列文章
更多 icon
同类精品
更多 icon
继续加载