学习一下-使用MutationObserver来监听DOM节点的变化

1,186 阅读4分钟

起因--先吹个壳子

学到这个api,是因为昨天公司里的一个小伙伴,公司大佬甩给他了一个打包好了的网站代码,要让他在加码的a b c 函数中加入公司自己的登录系统,然后用公司在那个网站创建的账号密码登录去调接口登录,这样全公司的人都可以用的公司自己的系统登录,(实际就是使用那个网站创建的账号登录的,本公司登录系统就是走个流程)

5B860B82-7F57-45d8-8F6B-75F50424B712.png

我那位小伙伴是在打包的js文件中用window.onload在文档加载完成后去插入一段js代码去appendChild一个button去跳转我公司自己的登录系统。

这时候遇到一个问题,在网络情况不好的时候有时会出现获取不到appendChild的父节点的DOM?

小编最先想到两个办法:

1、添加定时器去获取父节点,然后在插入自己的登录button

2、先获取到body 然后在body下插入script标签去加载他的逻辑代码

但是小编我并不满足,要是有什么api能直接监听某个dom节点是否渲染出来的就好了, 很遗憾小编没找到这种直接方法,但是小编找到了很多间接方法

1、MutationObserver API 来监听DOM节点的变化

2、轮询, 就是小编我自己想的第一方法

let checkExist = setInterval(function() {
   if (document.getElementById('myElement')) {
      console.log("找到了元素啦!");
      clearInterval(checkExist);
   }
}, 100); // 每100ms检查一次

3、第三方库,比如jq的ready(),很可惜我的小伙伴是原生大佬,直接操作dom节点就开干

A9F124AC-DA05-49f6-B069-B7DCB3A70AB0.png 4、使用Intersection Observer API 这个API可以用来观察元素何时进入或离开视口,也可以用来检测元素何时被渲染出来(小编后面有时间写个小demo哈(自己去看MDN),这里就不献丑了)。

0107BCF6-15E5-47fe-9EF4-6715BE48ACCA.png

主题-MutationObserver API讲解

上面说道 MutationObserver API 来监听DOM节点的变化,我们先直接看个demo 案例,大家打开控制台就能看到一句话: p标签已加载

MutationObserver()

创建一个MutationObserver实例,它会在DOM发生变化时调用回调函数

    // 创建一个新的MutationObserver实例,它会在DOM发生变化时调用回调函数
    var observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        console.log(mutation); // 打印结果的属性含义在下面mutation的对象属性
        // 检查是否有新的子节点被添加
        if (mutation.addedNodes.length) {
          var nodes = Array.from(mutation.addedNodes);
          nodes.forEach(function (node) {
            // 如果新添加的节点是你要监听的div
            if (node.id === "text") {
              console.log("p标签已加载");
              // 在这里执行你的操作

              // 如果你只想监听一次div的加载,你可以在这里停止观察
              observer.disconnect();
            }
          });
        }
      });
    });
    

mutation的对象属性

-   `type` —— 变动类型,以下类型之一:

    -   `"attributes"`:特性被修改了,
    -   `"characterData"`:数据被修改了,用于文本节点,
    -   `"childList"`:添加/删除了子元素。

-   `target` —— 更改发生在何处:`"attributes"` 所在的元素,或 `"characterData"` 所在的文本节点,或 `"childList"` 变动所在的元素,

-   `addedNodes/removedNodes` —— 添加/删除的节点,

-   `previousSibling/nextSibling` —— 添加/删除的节点的上一个/下一个兄弟节点,

-   `attributeName/attributeNamespace` —— 被更改的特性的名称/命名空间(用于 XML),

-   `oldValue` —— 之前的值,仅适用于特性或文本更改,如果设置了相应选项 `attributeOldValue`/`characterDataOldValue`

observe()

observe() 就是开始观察你指定的DOM节点,他有两个参数:

第一个是指定的DOM节点: 使用 document.getElementById()、document.querySelector()等获取到节点,注意节点一定要获取到,如果不获取去就会报错哦

     var boxDom = document.getElementById("box");
     observer.observe(boxDom, config);

第二个是MutationObserver的观察配置:

-   `childList` —— `node` 的直接子节点的更改,(默认值为 `false`)
-   `subtree` —— `node` 的所有后代的更改,(默认值为 `false`)
-   `attributes` —— `node` 的特性(attribute),(默认值则为 `false`)
-   `attributeFilter` —— 特性名称数组,只观察选定的特性。(例如:['class', 'id'])
-   `characterData` —— 是否观察 `node.data`(文本内容),(默认为false

disconnect()

disconnect() 就是停止观察,MutationObserver API 本身观察的范围就很广,如果你要观察的节点嵌套太深那么性能就会受影响, 所以如果你要使用MutationObserver就一定要记的停止它

     observer.observe(DOM, config); 启动监听
     observer.disconnect();  停止监听

嗯,今天的学习就到这里啦!

zpejK.gif