H5新增的一個特性Mutation Observer(變動觀察器)是監視DOM變動的接口。當DOM對象樹發生任何變動時,Mutation Observer會得到通知。他與對象事件的區別是事件是同步觸發的,而Mutation Observer則是異步觸發,DOM發生變動以后,並不會馬上觸發,而是要等到當前所有DOM操作都結束后才觸發。
目前支持Mutation Observer的瀏覽器有:Firefox(14+)、Chrome(26+)、Opera(15+)、IE(11+)和Safari(6.1+),可通過如下代碼來檢測:
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var mutationObserverSupport = !!MutationObserver;//true則支持
使用:
var observer = new MutationObserver(callback);//構造實例並指定回調函數 var article = document.querySelector('article'); var options = { 'childList': true, 'arrtibutes': true }; observer.observer(article, options);//實現監聽
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'])。
disconnect方法用來停止觀察。發生相應變動時,不再調用回調函數:observer.disconnect();
takeRecord方法用來清除變動記錄,即不再處理未處理的變動:observer.takeRecord();
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。
應用實例:檢測對象的屬性變動:
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);