美文网首页
MutationObserver 监听DOM

MutationObserver 监听DOM

作者: 带刀打天下 | 来源:发表于2020-11-16 11:41 被阅读0次
    介绍

    MutationObserver接口提供了监视对DOM树所做更改的能力。

    构造函数

    MutationObserver()创建并返回一个新的MutationObserver它会在指定的DOM发生变化时被调用。

    new MutationObserver(callback):当每次DOM发生变化的时候都会触发callback。

    等所有的DOM操作完成之后一次执行(异步)

    方法
    • disconnect()

      阻止 MutationObserver 实例继续接收的通知,直到再次调用其observe()方法,该观察者对象包含的回调函数都不会再被调用。

    • observe()

      配置MutationObserver在DOM更改匹配给定选项时,通过其回调函数开始接收通知。

    • takeRecords()

      从MutationObserver的通知队列中删除所有待处理的通知,并将它们返回到MutationRecord对象的新Array中。

    使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>MutationObserver</title>
    </head>
    <body>
      <div id="simple" class="test"> simple </div>
    </body>
    <script>
      // mutations 变动数组 observer 观察器实例
      var observer = new MutationObserver(function (mutations, observer) {
        mutations.forEach(function(mutation) {
          // 执行具体的操作
          // 例如:页面劫持
          console.log(mutation)
        })
      })
      // 开始监听页面根元素 html 变化
      observer.observe(document.getElementById("simple"), {
        attributes: true, // 属性变动
        characterData: true, // 节点内容或节点文本的变动
        childList: true, // 子节点的变动
        subtree: true, // 表示是否将观察器应用于该节点的所有后代节点
        attributeOldValue: true, // 表示观察 attributes 变动时,是否需要记录变动前的属性值
        characterDataOldValue: true, // 表示观察 characterData 变动时,是否需要记录变动前的值
        attributeFilter: ["style"] // 数组,表示需要观察的特定属性 (比如: ["class", "src"])
      });
    
      // document.getElementById("simple").innerText = 123;
      document.getElementById("simple").firstChild.nodeValue="test";
      // document.getElementById("simple").setAttribute("style", "background-color:blue; color:red; border:1px solid black");
      // document.getElementById("simple").style.height = "123px";
      // document.getElementById("simple").innerHTML = "<p>rrr</p>";
      
    
      // // 停止观察, 调用该方法后,DOM 再发生变动,也不会触发观察器
      // observer.disconnect();
      // // 清除变动记录,即不再处理未处理的变动,改方法返回变动记录的数组。
      // observer.takeRecords();
    
      // // 保存所有没有被观察器处理的变动
      // var changes = observer.takeRecords();
      // console.log(changes, "changes");
      // // 停止观察
      // observer.disconnect();
    
      // MutationRecord 对象
      // type: 观察的变动类型
      // target:发生变动的DOM节点
      // addedNodes:新增的DOM节点
      // removeNodes:删除的DOM节点
      // previousSibling:前一个同级节点,如果没有则返回null
      // nextSibling:下一个同级节点,如果没有则返回null
      // attributeName:发生变动的属性。如果这只了 attributeFilter,则只返回预先指定的属性
      // oldValue:变动前的值。这个属性只对 attribute和characterData变动有效,如果发生childList变动,则返回null
    </script>
    </html>
    
    示例
    • 水印不可删

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
      </head>
      <body>
        <div id="content"></div>
      </body>
      <script>
        function drawCanvas() {
          let content = document.getElementById("content");
          let divContainer = document.body.appendChild(document.createElement('div'));
          content.appendChild(divContainer);
          let waterMarkercanvas = document.createElement('canvas');
          let context = waterMarkercanvas.getContext('2d');
      
          divContainer.appendChild(waterMarkercanvas);
          divContainer.id = 'divContainer'
          let backgroundUrl = null;
      
          divContainer.style.height = window.innerHeight + 'px';
          divContainer.style.width = window.innerWidth + 'px';
      
      
          waterMarkercanvas.width = "400";
          waterMarkercanvas.height = "400";
      
          context.font = "20px";
          context.textAlign = "center";
          context.fillStyle = "#0000ff";
      
          context.fillText("我是水印", 100, 100);
      
          backgroundUrl = waterMarkercanvas.toDataURL('image/png');
          divContainer.style.backgroundImage = `url(${backgroundUrl})`;
        }
        drawCanvas();
        let callback = (mutations) => {
          mutations.forEach(mutation => {
              console.log(mutation,"mutation");
              if(mutation.removedNodes.length > 0 && mutation.removedNodes[0].id == "divContainer" && mutation.addedNodes.length <= 0) {
                setTimeout(function() {
                  console.log("新增")
                  drawCanvas();
                }, 3000)
              }
          });
        };
        let observer = new MutationObserver(callback);
        observer.observe(document.getElementById("content"), {
          childList: true,
          // subtree: true
        });
        console.log(document.getElementsByTagName("div"))
        setTimeout(function() {
          console.log("删除")
          document.getElementById("content").removeChild(document.getElementById("divContainer"));
        }, 3000)
      </script>
      </html>
      
    • 防止运营劫持:监控dom,不在白名单内和安全标签内的script或者iframe,都给予remove删除处理。

    相关文章

      网友评论

          本文标题:MutationObserver 监听DOM

          本文链接:https://www.haomeiwen.com/subject/iibabktx.html