MutationObserver對象
MutationObserver (W3C DOM4)
對象提供了監視對DOM
樹所做更改的能力,其被設計爲舊的Mutation Events
功能的替代品(該功能是DOM3 Events
規範的一部分)。
描述
Mutation Observer
用來監視DOM
變動,DOM
的任何變動,例如節點的增減、屬性的變動、文本內容的變動,在配置之後都可以通過回調函數來獲得通知。Mutation Observer
類似於事件的監聽DOM.addEventListener
方法,都可以在觸發某些變動的時候來執行回調函數,只不過Mutation Observer
是異步觸發,DOM
的變動並不會馬上觸發,在等到當前所有DOM
操作都結束才觸發。
observe
mutationObserver.observe(target[, options])
Mutation Observer
的observe()
方法配置了Mutation Observer
對象的回調方法,以開始接收與給定選項匹配的DOM
變化的通知。
target
:DOM
樹中的一個要觀察變化的DOM Node
,或者是被觀察的子節點樹的根節點。options
: 一個可選的MutationObserverInit
對象,此對象的配置項描述了DOM
的哪些變化應該提供給當前觀察者的callback
,在MutationObserverInit
對象中childList
、attributes
、characterData
三個屬性之中,至少有一個必須爲true
,否則會拋出TypeError
異常。childList
:表示子節點的變動,指新增,刪除或者更改字節點。attributes
:表示當前節點屬性的變動。characterData
:表示節點內容或節點文本的變動。subtree
:表示是否將該觀察器應用於該節點的所有後代節點。attributeOldValue
:表示觀察attributes
變動時,是否需要記錄變動前的屬性值。characterDataOldValue
:表示觀察characterData
變動時,是否需要記錄變動前的值。attributeFilter
:表示需要觀察的特定屬性,比如["class","src"]。
disconnect
mutationObserver.disconnect()
Mutation Observer
的disconnect()
方法告訴觀察者停止觀察變動,可以通過調用其observe()
方法來重用觀察者。
takeRecords
const mutationRecords = mutationObserver.takeRecords()
Mutation Observer
的takeRecords()
方法返回已檢測到但尚未由觀察者的回調函數處理的所有匹配DOM
更改的列表,使變更隊列保持爲空。此方法最常見的使用場景是在斷開觀察者之前立即獲取所有未處理的更改記錄,以便在停止觀察者時可以處理任何未處理的更改。
示例
Mutation Observer
的一個常用功能就是觀察DOM
元素的大小變更,通常是主動resize
造成了該元素的大小發生變化,所以需要觀察者來完成DOM
元素大小變更的副作用。在這裏完成了一個簡單的示例,觀察了attributes
與childList
兩個屬性值,並在attributes
中使用attributeFilter
來過濾只觀察style
屬性的變動,因爲在這裏是使用的contenteditable
來完成的DOM
元素的編輯,所以是使用了childList
來完成了子元素的變更觀察。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mutation Observer</title>
<style>
#observer-dom{
padding: 5px;
resize: both;
width: 300px;
height: 200px;
border: 1px solid #eee;
resize: both;
overflow: auto;
}
#observer-dom:empty:before {
content: attr(data-placeholder);
color: #aaa;
}
#observer-output{
width: 300px;
height: 200px;
border: 1px solid #eee;
margin-top: 20px;
}
</style>
</head>
<body>
<div id="observer-dom" contenteditable data-placeholder="Enter OR Resize"></div>
<textarea id="observer-output"></textarea>
</body>
<script>
const target = document.getElementById("observer-dom");
const textarea = document.getElementById("observer-output");
textarea.value = "output: \n";
const addOutput = log => {
textarea.value = textarea.value + log + "\n";
textarea.scrollTop = textarea.scrollHeight;
}
const config = { attributes: true, childList: true, attributeFilter: ["style"] };
const callback = function(mutationsList, observer) {
for(const mutation of mutationsList) {
console.log(mutation);
if(mutation.type === "childList"){
addOutput("ChildListAdded: " + mutation.addedNodes.length)
}else if(mutation.type === "attributes"){
addOutput("AttributeNameChange: " + mutation.attributeName)
}
}
};
const observer = new MutationObserver(callback);
observer.observe(target, config);
</script>
</html>
每日一題
https://github.com/WindrunnerMax/EveryDay
參考
https://juejin.cn/post/6949832945683136542
https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent
https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver