# MutationObserver

# 1、基础

MutationObserver赋予我们观察一个DOM变化的能力。观察者会观察 DOM 树中的单个Node节点,也可能会观察被指定节点的部分或者所有的子孙节点。

先看一个简单的伪代码,了解一下API。主要就是可以观察一个DOM元素, 然后可以通过options传入一些配置项。构造函数的回调会在DOM变化时被触发。

const observer = new MutationObserver(mutationList => {});
observer.observe(target, options);
// 停止监听
observer.disconnect();

target:DOM 树中的一个要观察变化的 DOM Node (可能是一个 Element),或者是被观察的子节点树的根节点。

options可以有如下属性

  • subtree 当为 true 时,将会监听以 target 为根节点的整个子树。包括子树中所有节点的属性,而不仅仅是针对 target。默认值为 false
  • childList 当为 true 时,监听 target 节点中发生的节点的新增与删除(同时,如果 subtreetrue,会针对整个子树生效)。默认值为 false
  • attributes 当为 true 时观察所有监听的节点属性值的变化。默认值为 true,当声明了 attributeFilterattributeOldValue,默认值则为 false
  • attributeFilter 一个用于声明哪些属性名会被监听的数组。如果不声明该属性,所有属性的变化都将触发通知。
  • attributeOldValue 当为 true 时,记录上一次被监听的节点的属性变化
  • characterData 当为 true 时,监听声明的 target 节点上所有字符的变化。默认值为 true,如果声明了 characterDataOldValue,默认值则为 false
  • characterDataOldValue 当为 true 时,记录前一个被监听的节点中发生的文本变化。默认值为 false

# 2、使用

下面是一个简单的demo。下图是MutationRecord的一些属性,个人理解可以根据MutationRecord的type属性判断是什么被更改, 通过addedNodes或者removedNodes判断是新增还是删除操作。 比如下面的childList就是新增删除元素。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>MutationObserver Demo</title>
  </head>
  <body>
    <div id="container">
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
      </ul>
      <p>sss</p>
    </div>
    <button onclick="addEl2()">add</button>
    <button onclick="deleteEl()">delete</button>
    <button onclick="changeAttr()">change attr</button>
    <button onclick="changeCharacterData()">Change Character Data</button>
    <script>
      const container = document.querySelector('#container');
      const ul = container.querySelector('ul');
      const observer = new MutationObserver(MutationRecordList => {
        console.log(MutationRecordList);
      });
      observer.observe(container, {
        subtree: true,
        childList: true,
        attributes: true
      });
      // 停止监听
      //   observer.disconnect();
      function addEl2() {
        addEl('111');
        addEl('222');
      }
      function addEl(text) {
        const el = document.createElement('div');
        el.textContent = text;
        el.style.color = 'red';
        container.appendChild(el);
      }
      function deleteEl() {
        container.removeChild(container.lastChild);
      }
      function changeAttr() {
        ul.setAttribute('id', 'ul-id');
      }
      function changeCharacterData() {
        container.classList.add('container');
      }
    </script>
  </body>
</html>

# 3、用于检测首屏加载

上次更新: 1/22/2025, 9:39:13 AM