监听DOM的一举一动 MutationObserver

1,022 阅读2分钟

MutationObserver是web API内建对象,它是一个观察者对象,用来监听指定DOM节点的变更事件。默认存在并兼容IE11以上的几乎所有浏览器。

image.png

创建

使用实例的方式创建,只有一个参数callback用来指定该对象触发变更事件时的回调函数:

const callback = records => { console.log(records) }
const observer = new MutationObserver(callback)

// 观察除了特性之外的所有变动
observer.observe(ele, {
  childList: true, // 观察直接子节点
  subtree: true, // 及其更低的后代节点
  characterDataOldValue: true // 将旧的数据传递给回调
});

/** records例子
[{
  addedNodes: NodeList []
  attributeName: null
  attributeNamespace: null
  nextSibling: null
  oldValue: "bold"
  previousSibling: null
  removedNodes: NodeList []
  target: text
  type: "characterData"
}]
**

方法

那怎么指定如何监听DOM元素呢?观察者实例有3个方法来实现相关操作:

  • observe(target, MutationObserverInit):设置监听对象,target是一个目标Node对象,第二个参数则是一个MutationObserverInit监听参数对象
  • disconnect():停止监听,即使再次调用observe也不会恢复
  • takeRecords():删除监听通知队列,并以数组形式返回当前队列里的MutationRecord对象,用来在停止监听前获取到剩余事件

监听参数MutationObserverInit

  • 监听范围
    • childList boolean,是否监视目标节点及其子节点的更改,默认false
    • subtree boolean,是否监听目标节点及其所有子孙节点的变更,默认false
  • 监听属性
    • attributes boolean,是否监听属性值变更,默认false
    • attrbuteFilter,string[],指定监听属性范围
    • attributeOldValue,boolean,是否返回旧属性值
  • 监听文本
    • characterData,boolean,是否监听#text文本内容的变更
    • characterDataOldValue,boolean,是否返回旧#text文本内容

响应对象MutationRecord

callback(records)被触发时会带上一个MutationRecord对象的数组records作为参数,告知开发者DOM变更的具体内容,MutationRecord的具体内容如下:

  • type 变更类型
    • 'attributes' 属性
    • 'characterData' 文本
    • 'childList' 添加/删除子节点
  • target 变更发生元素
  • addedNodes/removedNodes 添加/删除的节点
  • previousSibling/nextSibling 添加/删除的节点的上/下一个节点
  • attributeName/attributeNamespace 被更改的属性的名称/命名空间(用于 XML)
  • oldValue 之前的值(属性/文本),如果设置了attributeOldValue/characterDataOldValue才会出现

下面来看一个比较完整的例子:

<div contentEditable id="elem">Click and <b>edit</b>, please</div>

<script>
let observer = new MutationObserver(mutationRecords => {
  console.log(mutationRecords); // console.log(the changes)
});

// 观察除了特性之外的所有变动
observer.observe(elem, {
  childList: true, // 观察直接子节点
  subtree: true, // 及其更低的后代节点
  characterDataOldValue: true // 将旧的数据传递给回调
});
</script>

以上。 原创不易,欲转先告知,欢迎加我交流: 卡修