MutationObserver API

MutationObservr API 用于监视 DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。

DOM 发生变动都会触发 Mutation Observer 事件。但是,它跟事件还是有不同点:事件是同步触发的,DOM 变化立即触发相应的事件;Mutation Observer 是一部触发,DOM 变化不会马上触发,而是等当前所有 DOM 操作都结束后才触发。

总的来说,特点如下:

  • 它等待所有脚本任务完成后,才会运行(即一步触发方式)
  • 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动
  • 它既可以观察 DOM 的所有类型变动,也可以指定只观察某类变动

接口定义

declare var MutationObserver: {
  new(callback: Mutationcallback): MutationObserver;

  prototype: MutationObserver;
}

interface MutationObserver {
  constructor(MutationCallback callback);

  /**
   * @param target 被观察的 DOM 节点
   * @param options 配置对象(指定所要观察特征)
   */
  observer(target: Node, options?: MutationObserverInit): void;

  disconnect(): void;

  takeRecords(): MutationRecord[];
}

interface MutationObserverInit {
  /* 观察特定属性 */
  attributeFilter?: string[];
  /* 观察 attributes 变动时,是否需要记录变动前的属性值 */
  attributeOldValue?: boolean;
  /* 属性的变动*/
  attributes?: boolean;
  /* 节点内容或节点文本的变动*/
  characterData?: boolean;
  /* 观察 characterData 变动,是否需要记录变动前的值 */
  characterDataOldValue?: boolean;
  /* 子节点的变动(新增、删除或者更改) */
  childList?: boolean;
  /* 是否将观察器应用于该节点的所有后代节点 */
  subtree?: boolean;
}

interface MutationRecord {

}

应用实战

基本用法

// 获取需要观察变动的元素节点
const targetElement = document.getElementById('observer');

// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };

// 当观察到变动时执行的回调函数
const onMutationObserverChange = function(mutationsList, observer) {
  for (let mutation of mutationsList) {
    if (mutation.type === 'childList') {
      console.log('A child node has been added or removed');
    } else if (mutation.type === 'attributes') {
      console.log(mutation.attributeName);
    }
  }
};

// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(onMutationObserverChange);

// 以上述配置开始观察目标节点
observer.observe(targetNode, config);

// 停止观察
observer.disconnect();

参考资料