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

相關文章
相關標籤/搜索