MutationObserver 是 JavaScript 中用于监听 DOM 变化的强大 API,能够高效地监测节点添加/删除、属性修改、文本内容变更等操作,适用于动态内容加载、表单验证、响应式布局等场景。以下是其完整用法指南:
一、核心概念
- 异步触发:所有 DOM 变化会先被记录,待其他脚本执行完成后统一触发回调,避免频繁操作导致的性能问题。
 - 弱引用机制:观察器对节点的引用为弱引用,节点被移除且不可访问时会被垃圾回收,不影响内存管理。
 - 配置优化 :通过 
config对象指定监听类型,避免不必要的回调调用以节省资源。 
二、基本用法
1. 创建观察器实例
            
            
              javascript
              
              
            
          
          const observer = new MutationObserver((mutationsList, observer) => {
  mutationsList.forEach(mutation => {
    console.log('变化类型:', mutation.type);
    // 处理具体变化(如新增节点、属性修改等)
  });
});
        - 参数 :回调函数接收两个参数:
mutationsList:包含所有 DOM 变化的MutationRecord对象数组。observer:观察器实例本身,可用于停止观察。
 
2. 配置观察选项
通过 config 对象指定监听类型,常用配置项如下:
| 配置项 | 说明 | 
|---|---|
childList | 
监听子节点的添加或删除(true/false)。 | 
attributes | 
监听属性变化(true/false)。 | 
attributeFilter | 
指定监听的属性名数组(如 ['class', 'id']),不指定则监听所有属性。 | 
attributeOldValue | 
记录属性旧值(需 attributes: true)。 | 
characterData | 
监听文本节点内容变化(true/false)。 | 
characterDataOldValue | 
记录文本旧值(需 characterData: true)。 | 
subtree | 
监听所有后代节点的变化(true/false)。 | 
示例:
            
            
              javascript
              
              
            
          
          const config = {
  childList: true,       // 监听子节点变化
  attributes: true,      // 监听属性变化
  subtree: true,         // 监听所有后代节点
  attributeFilter: ['class', 'id'] // 仅监听 class 和 id 属性
};
        3. 启动观察
            
            
              javascript
              
              
            
          
          const targetNode = document.getElementById('target');
observer.observe(targetNode, config);
        - 参数 :
targetNode:要监听的 DOM 节点。config:观察选项对象。
 
4. 停止观察
- 
停止所有监听 :
javascriptobserver.disconnect(); - 
获取未处理的变化记录 (同步执行):
javascriptconst records = observer.takeRecords(); console.log(records); // 返回未处理的 MutationRecord 数组 
三、高级技巧
1. 动态内容加载
监听 AJAX 插入的内容或动态加载的组件:
            
            
              javascript
              
              
            
          
          const contentObserver = new MutationObserver((mutationsList) => {
  mutationsList.forEach(mutation => {
    if (mutation.type === 'childList') {
      mutation.addedNodes.forEach(node => {
        if (node.nodeType === 1) { // 元素节点
          console.log('新增元素:', node);
          // 处理新加载内容的逻辑
        }
      });
    }
  });
});
const config = { childList: true, subtree: true };
contentObserver.observe(document.body, config);
        2. 表单验证
监听表单元素属性变化(如 disabled、value
            
            
              javascript
              
              
            
          
          const formObserver = new MutationObserver((mutationsList) => {
  mutationsList.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'value') {
      console.log('表单值变化:', mutation.target.value);
      // 执行验证逻辑
    }
  });
});
const input = document.getElementById('username');
formObserver.observe(input, { attributes: true, attributeOldValue: true });
        3. 响应式布局
根据 DOM 变化动态调整布局:
            
            
              javascript
              
              
            
          
          const layoutObserver = new MutationObserver(() => {
  adjustLayout(); // 自定义布局调整函数
});
const container = document.getElementById('container');
layoutObserver.observe(container, { childList: true, subtree: true });
        4. 自定义组件开发
监听组件内部 DOM 变化并更新状态:
            
            
              javascript
              
              
            
          
          class CustomComponent {
  constructor(element) {
    this.element = element;
    this.observer = new MutationObserver((mutationsList) => {
      mutationsList.forEach(mutation => {
        if (mutation.type === 'childList') {
          this.updateState(); // 自定义状态更新函数
        }
      });
    });
    this.observer.observe(this.element, { childList: true, subtree: true });
  }
  updateState() {
    console.log('组件状态更新');
  }
}
        四、注意事项
- 性能优化 :
- 避免过度监听(如不必要的 
subtree: true)。 - 使用 
attributeFilter缩小监听范围。 
 - 避免过度监听(如不必要的 
 - 文本节点监听限制 :
- 输入中文字符时可能无法触发 
characterData变化。 - 文本节点被完全删除后,新输入的文本会生成新节点,需通过 
childList监听父容器。 
 - 输入中文字符时可能无法触发 
 - 与 
IntersectionObserver的区别 :MutationObserver监听 DOM 变化,IntersectionObserver监听元素可见性变化。MutationObserver需手动停止监听(disconnect()),IntersectionObserver可通过unobserve()停止指定元素监听。
 
五、示例汇总
示例 1:监听元素属性变化
            
            
              javascript
              
              
            
          
          const box = document.getElementById('box');
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === 'attributes') {
      console.log('属性变化:', mutation.attributeName, '旧值:', mutation.oldValue);
    }
  });
});
const config = {
  attributes: true,
  attributeOldValue: true,
  attributeFilter: ['class', 'style']
};
observer.observe(box, config);
        示例 2:监听子元素添加/删除
            
            
              javascript
              
              
            
          
          const list = document.getElementById('list');
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === 'childList') {
      mutation.addedNodes.forEach(node => {
        if (node.nodeType === 1) console.log('新增子元素:', node);
      });
      mutation.removedNodes.forEach(node => {
        if (node.nodeType === 1) console.log('移除子元素:', node);
      });
    }
  });
});
observer.observe(list, { childList: true, subtree: true });
        示例 3:监听文本内容变化
            
            
              javascript
              
              
            
          
          const editableDiv = document.getElementById('editable');
const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === 'characterData') {
      console.log('文本变化:', mutation.target.nodeValue);
    }
  });
});
observer.observe(editableDiv, { characterData: true, subtree: true });
        六、总结
MutationObserver 是监测 DOM 变化的理想工具,通过合理配置可实现动态内容加载、表单验证、响应式布局等功能。使用时需注意性能优化,避免过度监听,并根据实际需求选择合适的监听类型。结合具体场景,MutationObserver 能显著提升网页的交互性和动态响应能力。