跳到主要内容

Mutation Observer

Mutation Observer 表示变动观察器,监视 DOM 变化的接口。当 DOM 对象树发生变化时, Mutation Observer 会接到通知。

  • 事件是同步触发的,也就是说 DOM 发生变动会立即触发相应的事件
  • Mutation Observer 是异步触发的, DOM 触发后,必不会马上触发而是要等到当前所有的 DOM 操作完毕才会触发。

Mutation Observer 具有以下特点:

  • 等待所有的脚本任务完毕后,才会运动,而且只触发一次
  • 把 DOM 变动记录成一个数组,而不是一条条的个别处理 DOM 变动
  • 可以观察发生在 DOM 节点的变动,也可以观察某一类变动

支持检测

var MutationObserver =
window.MutationObserver ||
window.WebkitMutationObserver ||
widow.MozMutationObserver;
var MutationObserverSupport = !!MutationObserver;

使用步骤

创建实例

使用 MutationObserver() 构造函数,新建一个实例,同时指定这个实例的回调函数:

var observer = new MutationObserver(callback);

指定观测对象

使用 observe() 方法指定要观察的 DOM 元素,以及要观察的特定待动:

var article = document.querySelector('article');
var options = { childList: true, attributes: true };
observer.observer(article, options);

MutationObserver 所观察的 DOM 变动,包含下列类型,设置为布尔型:

  • childList  :子元素的变化
  • attributes : 属性的变动
  • characterData :节点内容或节点文本的变动
  • attributeOldValue : 若设置为 true ,则表示需要记录变动前的属性值
  • characterDataOldValue : 如果设置为 true ,则表示需要记录变动前的数据值值
  • attributeFilter : 值为一个数组,表示要观察的特定属性,如 ['class','str']
  • subtree : 所有下属节点(包括子节点和子节点的子节点)的变动

停止观察

使用 disconnect() 方法停止观察:

observe.disconnect();

清除记录

使用 takeRecord() 方法清除变动记录,即不再处理未变动的变动。

DOM 每一次变动,就会产生一个变动记录。该记录对应一个 MutationRecord 对象,该对象包含了与变动相关的所有信息。 Mutation Observer 进行处理的一个个变动对象所组成的数组。

  • type : 观察变动的类型,如 : attribute 、 characterData 、 childList
  • target : 发生变动的 DOM 对象
  • addedNodes : 新增的 DOM 节点
  • removeNodes : 删除的 DOM 节点
  • previousSibling : 前一个同级 DOM 对象,如果没有则返回 null
  • nextSibling :下一个同级的 DOM 对象,如果没有则返回 null
  • attributeName : 发生变动的属性。如果设置了 attributeFilter ,则只返回指定的属性
  • oldValue : 变动前的值。这个属性只对 attribute 和 characterData 变动有效;如果发生 childList 变动,则返回 null 。

触发事件

使用 MutationObserver 对象时可能触发的各种事件必须设定 MutationObserver 选项值说明:

  • DOMAttrModified : attributes : true ( , attributeOldValue : true )(, attributeFilter:["attributeName"])
  • DOMAttributeNameChanged : attributes : true (, attributeOldValue : true)(, attributeFilter : ["attributeName"])
  • DOMCharacterDataModified : characterData : true (,characterDataOldValue : rue)
  • DOMNodeInserted : childList : true( , subtree : true)
  • DOMNodeInsertedInfoDocument : childList : true( , subtree : true)
  • DOMNodeRemoved : childList :true (,subtree : true)
  • DOMNodeRemovedFormDocument : childList : true( , subtree : true)
  • DOMSubtreeModified : childList : true, subtree : true

案例 1

<div
id="div"
style="height:
100px;width:100%;background-color:pink;"
></div>
<input type="button" value="插入 span 元素" onclick="changeDiv();" />
<script type="text/javascript">
function onchange(mutationRecords, mutationObserver) {
alert('检测到 DOM 变化');
console.log(mutationRecords);
console.log(mutationObserver);
}
var div = document.getElementById('div');
var mo = new window.MutationObserver(onchange),
options = { childList: true };
mo.observe(div, options);
function changeDiv() {
var span = document.createElement('span');
span.innerHTML = '我是一个 span 元素';
div.appendChild(span);
}
</script>

案例2

<a id="a1" href="#a">链接1</a> <a id="a2" href="#b">链接2</a>
<input type="button" value="修改 a 元素" onclick="changeA();" />
<script type="text/javascript">
function onchange(mutationRecords, mutationObserver) {
for (var i = 0; i <script mutationRecords.length; i++) console.log("修改前的"
+ mutationRecords[i].attributeName + "属性为:" + mutationRecords[i].oldValue); }
var a1El = document.getElementById('a1');
var a2El = document.getElementById('a2'); var attr = ["href"];
var mo = new window.MutationObserver(onchange), options = {
attributes: true,
attributeFilter: attr, attributeOldValue: true };
mo.observe(a1El, options); mo.observe(a2El,
options); function changeA() {
a1El.setAttribute("href", "http://www.baidu.com");
a2El.setAttribute("href", "http://www.weibo.com"); }
</script>