HTML5新特性之Mutation Observer

一、概述

Mutation Observer(变更观察器)是监视DOM变更的接口。当DOM对象树发生任何变更时,Mutation Observer会获得通知。javascript

要概念上,它很接近事件。能够理解为,当DOM发生变更会触发Mutation Observer事件。可是,它与事件有一个本质不一样:事件是同步触发,也就是说DOM发生变更马上会触发相应的事件;Mutation Observer则是异步触发,DOM发生变更之后,并不会立刻触发,而是要等到当前全部DOM操做都结束后才触发。html

这样设计是为了应付DOM变更频繁的状况。举例来讲,若是在文档中连续插入1000个段落(p元素),会连续触发1000个插入事件,执行每一个事件的回调函数,这极可能形成浏览器的卡顿;而Mutation Observer彻底不一样,只在1000个段落都插入结束后才会触发,并且只触发一次。java

注:在控制台可看到logreact

Mutation Observer有如下特色:数组

  • 它等待全部脚本任务完成后,才会运行,即采用异步方式
  • 它把DOM变更记录封装成一个数组进行处理,而不是一条条地个别处理DOM变更。
  • 它便可以观察发生在DOM节点的全部变更,也能够观察某一类变更

目前,Firefox(14+)、Chrome(26+)、Opera(15+)、IE(11+)和Safari(6.1+)支持这个API。Safari 6.0和Chrome 18-25使用这个API的时候,须要加上WebKit前缀(WebKitMutationObserver)。可使用下面的表达式检查浏览器是否支持这个API。浏览器

var MutationObserver = window.MutationObserver ||
    window.WebKitMutationObserver ||
    window.MozMutationObserver;

var mutationObserverSupport = !!MutationObserver;

二、使用方法

首先,使用MutationObserver构造函数,新建一个实例,同时指定这个实例的回调函数。less

var observer = new MutationObserver(callback);

2.1 observer方法

observer方法指定所要观察的DOM元素,以及要观察的特定变更。dom

var article = document.querySelector('article');

var options = {
    'childList': true,
    'arrtibutes': true
};

observer.observer(article, options);

上面代码首先指定,所要观察的DOM元素提article,而后指定所要观察的变更是子元素的变更和属性变更。最后,将这两个限定条件做为参数,传入observer对象的observer方法。异步

MutationObserver所观察的DOM变更(即上面代码的option对象),包含如下类型:函数

  • childList:子元素的变更
  • attributes:属性的变更
  • characterData:节点内容或节点文本的变更
  • subtree:全部下属节点(包括子节点和子节点的子节点)的变更

想要观察哪种变更类型,就在option对象中指定它的值为true。须要注意的是,不能单独观察subtree变更,必须同时指定childList、attributes和characterData中的一种或多种。

除了变更类型,option对象还能够设定如下属性:

  • attributeOldValue:值为true或者为false。若是为true,则表示须要记录变更前的属性值。
  • characterDataOldValue:值为true或者为false。若是为true,则表示须要记录变更前的数据值。
  • attributesFilter:值为一个数组,表示须要观察的特定属性(好比['class', 'str'])。

2.2  disconnect方法和takeRecord方法

disconnect方法用来中止观察。发生相应变更时,再也不调用回调函数。

observer.disconnect();

takeRecord方法用来清除变更记录,即再也不处理未处理的变更。

observer.takeRecord

2.3 MutationRecord对象

DOM对象每次发生变化,就会生成一条变更记录。这个变更记录对应一个MutationRecord对象,该对象包含了与变更相关的全部信息。Mutation Observer进行处理的一个个变更对象所组成的数组。

MutationRecord对象包含了DOM的相关信息,有以下属性:

  • type:观察的变更类型(attribute、characterData或者childList)。
  • target:发生变更的DOM对象。
  • addedNodes:新增的DOM对象。
  • removeNodes:删除的DOM对象。
  • previousSibling:前一个同级的DOM对象,若是没有则返回null。
  • nextSibling:下一个同级的DOM对象,若是没有就返回null。
  • attributeName:发生变更的属性。若是设置了attributeFilter,则只返回预先指定的属性。
  • oldValue:变更前的值。这个属性只对attribute和characterData变更有效,若是发生childList变更,则返回null。

三、实例

3.1 子元素的变更

下面的例子说明若是读取变更记录。

var callback = function(records) {
    records.map(function(record) {
        console.log('Mutation type: ' + record.type);
        console.log('Mutation target: ' + record.target);
    });
};

var mo = new MutationObserver(callback);

var option = {
    'childList': true,
    'subtree': true
};

mo.observer(document.body, option);

上面代码的观察器,观察body元素的全部下级元素(childList表示观察子元素,subtree表示观察子元素的下级元素)的变更。回调函数会在控制台显示全部变更的类型和目标元素。

3.二、属性的变更

下面的例子说明如何追踪属性的变更。

var callback = function(records) {
    records.map(function(record) {
        console.log('Previous attribute value: ' + record.oldValue);
    });
};

var mo = new MutationObserver(callback);

var element = document.getElementById('#my_element');

var option = {
    'attribute': true,
    'attributeOldValue': true
};

mo.observer(element, option);

上面代码先设定追踪属性变更('attributes': true),而后设定记录变更前的值。实际发生变更时,会将变更前的值显示在控制台。

四、参考连接

[1] Tiffany Brown, Getting to know mutation observers

[2] Michal Budzynski, JavaScript: The less know parts.DOM Mutations

[3] Jeff Griffiths, DOM MutationObserver - reacting to DOM changes without killing browser performance

[4] Ruanyf, Mutation Observer

相关文章
相关标签/搜索