MutationObserver 監聽DOM樹變化

1 概述

Mutation observer 是用于代替 Mutation events 作為觀察DOM樹結構發生變化時,做出相應處理的API。為什么要使用mutation observer 去代替 mutation events 呢,我們先了解一下mutation events

Mutation Events

Mutation events 是在 DOM3中定義,用于監聽DOM樹結構變化的事件

它簡單的用法如下:

document.getElementById('list').addEventListener("DOMSubtreeModified", function(){
  console.log('列表中子元素被修改');
}, false);

Mutation 事件列表

  • DOMAttrModified
  • DOMAttributeNameChanged
  • DOMCharacterDataModified
  • DOMElementNameChanged
  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMNodeInsertedIntoDocument
  • DOMSubtreeModified

其中DOMNodeRemoved,DOMNodeInserted 和 DOMSubtreeModified 分別用于 監聽元素子項的刪除,新增,修改(包括刪除和新增),
DOMAttrModified 是監聽元素屬性的修改,并且能夠提供具體的修改動作。

Mutation Events遇到的問題
  • 瀏覽器兼容性問題
    IE9不支持Mutation Events
    Webkit內核不支持DOMAttrModified特性,
    DOMElementNameChanged和DOMAttributeNameChanged 在Firefox上不被支持。
  • 性能問題
    1.Mutation Events是同步執行的,它的每次調用,都需要從事件隊列中取出事件,執行,然后事件隊列中移除,期間需要移動隊列元素。如果事件觸發的較為頻繁的話,每一次都需要執行上面的這些步驟,那么瀏覽器會被拖慢。
    2.Mutation Events本身是事件,所以捕獲是采用的是事件冒泡的形式,如果冒泡捕獲期間又觸發了其他的MutationEvents的話,很有可能就會導致阻塞Javascript線程,甚至導致瀏覽器崩潰。

Mutation Observer

Mutation Observer 是在DOM4中定義的,用于替代 mutation events 的新API,它的不同于events的是,所有監聽操作以及相應處理都是在其他腳本執行完成之后異步執行的,并且是所以變動觸發之后,將變得記錄在數組中,統一進行回調的,也就是說,當你使用observer監聽多個DOM變化時,并且這若干個DOM發生了變化,那么observer會將變化記錄到變化數組中,等待一起都結束了,然后一次性的從變化數組中執行其對應的回調函數。

Mutation Observer 的瀏覽器兼容范圍


兼容性

2 方法

構造函數

用來實例化一個Mutation觀察者對象,其中的參數是一個回調函數,它是會在指定的DOM節點發送變化后,執行的函數,并且會被傳入兩個參數,一個是變化記錄數組(MutationRecord),另一個是觀察者對象本身

new MutationObserver(function(records, itself){});
observe

在觀察者對象上,注冊需要觀察的DOM節點,以及相應的參數

void observe(Node target, optional MutationObserverInit options)

其中的可選參數 MutationObserverInit的屬性如下:

childLIst 觀察目標節點的子節點的新增和刪除。
attributes 觀察目標節點的屬性節點(新增或刪除了某個屬性,以及某個屬性的屬性值發生了變化)。
characterData 如果目標節點為characterData節點(一種抽象接口,具體可以為文本節點,注釋節點,以及處理指令節點)時,也要觀察該節點的文本內容是否發生變化
subtree 觀察目標節點的所有后代節點(觀察目標節點所包含的整棵DOM樹上的上述三種節點變化)
attributeOldValue 在attributes屬性已經設為true的前提下, 將發生變化的屬性節點之前的屬性值記錄下來(記錄到下面MutationRecord對象的oldValue屬性中)
characterDataOldValue 在characterData屬性已經設為true的前提下,將發生變化characterData節點之前的文本內容記錄下來(記錄到下面MutationRecord對象的oldValue屬性中)
attributeFilter 一個屬性名數組(不需要指定命名空間),只有該數組中包含的屬性名發生變化時才會被觀察到,其他名稱的屬性發生變化后會被忽略想要設置那些刪選參數的話,

如果想要使用哪個參數的話,就將其值設定為true

disconnect

暫定在觀察者對象上設置的節點的變化監聽,直到重新調用observe方法

takeRecords

在觀察者對象上調用takeRecords 會返回 其觀察節點上的變化記錄(MutationRecord)數組
其中MutationRecord數組也會作為,觀察者初始化時的回調函數的第一個參數
其包含的屬性如下:

type 如果是屬性發生變化,則返回attributes.如果是一個CharacterData節點發生變化,則返回characterData,如果是目標節點的某個子節點發生了變化,則返回childList.
target 返回此次變化影響到的節點,具體返回那種節點類型是根據type值的不同而不同的,如果type為attributes,則返回發生變化的屬性節點所在的元素節點,如果type值為characterData,則返回發生變化的這個characterData節點.如果type為childList,則返回發生變化的子節點的父節點.
addedNodes 返回被添加的節點
removedNodes 返回被刪除的節點
previousSibling 返回被添加或被刪除的節點的前一個兄弟節點
nextSibling 返回被添加或被刪除的節點的后一個兄弟節點
attributeName 返回變更屬性的本地名稱
oldValue 根據type值的不同,返回的值也會不同.如果type為attributes,則返回該屬性變化之前的屬性值.如果type為characterData,則返回該節點變化之前的文本數據.如果type為childList,則返回null

3 使用實例

// Firefox和Chrome早期版本中帶有前綴
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
// 選擇目標節點
var target = document.querySelector('#some-id'); 
// 創建觀察者對象
var observer = new MutationObserver(function(mutations) {  
  mutations.forEach(function(mutation) { 
    console.log(mutation.type); 
  }); 
}); 
// 配置觀察選項:
var config = { attributes: true, childList: true, characterData: true } 
// 傳入目標節點和觀察選項
observer.observe(target, config); 
// 隨后,你還可以停止觀察
observer.disconnect();

4 參考鏈接

[1].MDN Mutation Observer
[2].將突變事件和屬性更改事件遷移到突變觀察者

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容