Mutation Observer(變更觀察器)是監視DOM變更的接口。當DOM對象樹發生任何變更時,Mutation Observer會獲得通知。javascript
要概念上,它很接近事件。能夠理解爲,當DOM發生變更會觸發Mutation Observer事件。可是,它與事件有一個本質不一樣:事件是同步觸發,也就是說DOM發生變更馬上會觸發相應的事件;Mutation Observer則是異步觸發,DOM發生變更之後,並不會立刻觸發,而是要等到當前全部DOM操做都結束後才觸發。html
目前,Firefox(14+)、Chrome(26+)、Opera(15+)、IE(11+)和Safari(6.1+)支持這個API。Safari 6.0和Chrome 18-25使用這個API的時候,須要加上WebKit前綴(WebKitMutationObserver)。可使用下面的表達式檢查瀏覽器是否支持這個API。java
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var mutationObserverSupport = !!MutationObserver;
二、使用方法
首先,使用MutationObserver構造函數,新建一個實例,同時指定這個實例的回調函數。react
var observer = new MutationObserver(callback);
2.1 observer方法
observer方法指定所要觀察的DOM元素,以及要觀察的特定變更。數組
var article = document.querySelector('article'); var options = { 'childList': true, 'arrtibutes': true }; observer.observer(article, options);
上面代碼首先指定,所要觀察的DOM元素提article,而後指定所要觀察的變更是子元素的變更和屬性變更。最後,將這兩個限定條件做爲參數,傳入observer對象的observer方法。瀏覽器
MutationObserver所觀察的DOM變更(即上面代碼的option對象),包含如下類型:less
- childList:子元素的變更
- attributes:屬性的變更
- characterData:節點內容或節點文本的變更
- subtree:全部下屬節點(包括子節點和子節點的子節點)的變更
想要觀察哪種變更類型,就在option對象中指定它的值爲true。須要注意的是,不能單獨觀察subtree變更,必須同時指定childList、attributes和characterData中的一種或多種。dom
除了變更類型,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