MutationObserver DOM變化的觀察
簡單的給MutationObserver做個測試及總結筆記。
MutationObserver,window上的一個(構造)函式,可以通過其建立的觀察者(觀察物件)達到觀察DOM的變化的效果。
可適用的需求:開發者在DOM變化過程中的debug、根據頁面變化處理不同的資源、攔截網頁是否被注入動態內容載入的指令碼等等...
簡單的案例程式碼如下,比如觀察屬性變化:
<button id="J_click">click</button> <div id="J_dom" data-num="1">hello</div> <script> var dom = document.getElementById('J_dom'); var domObservable = new MutationObserver(function (mutationRecord) { console.log('mutationRecord : ', mutationRecord) }); document.getElementById('J_click').addEventListener('click', domChange, !1); domObservable.observe(dom, { attributes: true, attributeOldValue: true }) function domChange() { dom.setAttribute('data-num', +(dom.getAttribute('data-num')) + 1); } </script>
點選"click"按鈕,J_dom的data-num屬性從0變為1。控制檯輸出如下MutationRecord物件列表:
MutationObserver 建構函式需要傳入一個回撥函式用以執行觀察到DOM變化後需要做的操作,回撥函式以MutationRecord物件列表作為引數。
MutationRecord物件列表
MutationRecord物件包含以下屬性:
1. type,DOM變化的型別,DOM屬性變化為"attributes";DOM內資料變化為"characterData";子節點樹結構變化為"childList";
2. target,如果如果type不為"childList",則代表發生變化的節點;如果type為"childList",則是被操作子節點(新增或刪除)的父節點;
3. addedNodes,被觀察的DOM內新增的節點列表;
4. removedNodes,被觀察的DOM內移除的節點列表;
5. previousSibling,被新增或移除節點之前的兄弟節點;
6. nextSibling,被新增或移除節點之後的兄弟節點;
7. attributeName,被修改屬性的屬性名;
8. attributeNamespace,被修改屬性的名稱空間;
9. oldValue,舊值,根據type而返回對應的舊屬性或舊資料。
觀察者(觀察物件)
觀察者物件上存在3個操作方法:observe、takeRecords、disconnect。
observe方法指定一個被觀察的DOM,配置該節點內的哪些變化需要被觀察。方法使用如下:
var domObservable = new MutationObserver(function (mutationRecord) { // 變化後的處理程式碼 }); domObservable.observe(/* 被觀察的DOM */, /* 配置引數 */{ subtree: false,// 觀察範圍是否包含子節點的變化,true則包括,false則不包括 childList: false,// 被觀察的節點的子節點變化,true則觀察,false則不觀察 attributes: false,// 被觀察的節點的屬性變化,true則觀察,false則不觀察 attributeOldValue: false,// MutationRecord物件上是否返回被觀察的節點的屬性變化之前的舊值,true則返回,false則不返回 attributeFilter: [/* 指定被觀察的屬性列表 */],// attributes為true時生效,比如設定了列表為['class'],則只觀察class的變化 characterData: false,// 被觀察的節點的資料變化,true則觀察,false則不觀察 characterDataOldValue: false// MutationRecord物件上是否返回被觀察的節點的資料變化之前的舊值,true則返回,false則不返回 }); /** * 注意: * 在attributes未被配置的情況下,如果attributeOldValue為true或者attributeFilter被設定,則attributes預設為true。 * 在characterData未被配置的情況下,如果characterDataOldValue為true,則characterData預設為true。 */
takeRecords方法返回當前操作後的MutationRecord物件列表。方法使用如下:
<button id="J_takeRecords">take records</button> <div id="J_dom" data-num="1"> <span id="J_words">0</span> <div id="J_subDom"></div> </div> <script> var value = 0; var operateDom = document.getElementById('J_dom'); var wordsDom = document.getElementById('J_words'); var takeRecordsBtn = document.getElementById('J_takeRecords'); takeRecordsBtn.addEventListener('click', takeRecords, !1); function takeRecords() { console.log('%c both change attribute and subtree', 'color:blue'); operateDom.setAttribute('data-num', +(operateDom.getAttribute('data-num')) + 1); wordsDom.innerText = wordsDom.innerText === '0' ? '零' : '0'; var result = domObservable.takeRecords(); console.log(result); } var domObservable = new MutationObserver(function (mutationsList) { console.log('mutationsList ', mutationsList); }) domObservable.observe(operateDom, { subtree: true, attributes: true, attributeOldValue: true, characterData: true, characterDataOldValue: true }); </script> <!-- 點選"take records"按鈕,J_dom的data-num屬性從0變為1,J_words裡的0變成零 --> <!-- 分別為一次attrbutes和一次characterData變化,takeRecords方法被呼叫返回一個包含兩次變化的MutationRecord物件列表。-->
disconnect方法移除該觀察者上的所有觀察並清空該物件的MutationRecord物件列表。
最後,MutationObserver的相容性如下:
嗯,還算行...