MutationObserver 完整用法指南

MutationObserver 是 JavaScript 中用于监听 DOM 变化的强大 API,能够高效地监测节点添加/删除、属性修改、文本内容变更等操作,适用于动态内容加载、表单验证、响应式布局等场景。以下是其完整用法指南:

一、核心概念

  1. 异步触发:所有 DOM 变化会先被记录,待其他脚本执行完成后统一触发回调,避免频繁操作导致的性能问题。
  2. 弱引用机制:观察器对节点的引用为弱引用,节点被移除且不可访问时会被垃圾回收,不影响内存管理。
  3. 配置优化 :通过 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. 停止观察

  • 停止所有监听

    javascript 复制代码
    observer.disconnect();
  • 获取未处理的变化记录 (同步执行):

    javascript 复制代码
    const 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. 表单验证

监听表单元素属性变化(如 disabledvalue

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('组件状态更新');
  }
}

四、注意事项

  1. 性能优化
    • 避免过度监听(如不必要的 subtree: true)。
    • 使用 attributeFilter 缩小监听范围。
  2. 文本节点监听限制
    • 输入中文字符时可能无法触发 characterData 变化。
    • 文本节点被完全删除后,新输入的文本会生成新节点,需通过 childList 监听父容器。
  3. 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 能显著提升网页的交互性和动态响应能力。

相关推荐
一晌小贪欢6 小时前
【Html模板】赛博朋克风格数据分析大屏(已上线-可预览)
前端·数据分析·html·数据看板·看板·电商大屏·大屏看板
墨寒博客栈6 小时前
Linux基础常用命令
java·linux·运维·服务器·前端
野生龟6 小时前
designable和formily实现简单的低代码平台学习
前端
路多辛6 小时前
为什么我要做一个开发者工具箱?聊聊 Kairoa 的诞生
前端·后端
jerryinwuhan6 小时前
理论及算法_时间抽取论文
前端·算法·easyui
秋子aria6 小时前
模块的原理及使用
前端·javascript
菜市口的跳脚长颌6 小时前
一个 Vite 打包配置,引发的问题—— global: 'globalThis'
前端·vue.js·vite
胖虎2656 小时前
实现无缝滚动无滚动条的 Element UI 表格(附完整代码)
前端·vue.js
小左OvO6 小时前
基于百度地图JSAPI Three的城市公交客流可视化(一)——线路客流
前端