MutationObserver對象

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 Observerobserve()方法配置了Mutation Observer對象的回調方法,以開始接收與給定選項匹配的DOM變化的通知。

  • target: DOM樹中的一個要觀察變化的DOM Node,或者是被觀察的子節點樹的根節點。
  • options: 一個可選的MutationObserverInit對象,此對象的配置項描述了DOM的哪些變化應該提供給當前觀察者的callback,在MutationObserverInit對象中childListattributescharacterData三個屬性之中,至少有一個必須爲true,否則會拋出TypeError異常。
    • childList:表示子節點的變動,指新增,刪除或者更改字節點。
    • attributes:表示當前節點屬性的變動。
    • characterData:表示節點內容或節點文本的變動。
    • subtree:表示是否將該觀察器應用於該節點的所有後代節點。
    • attributeOldValue:表示觀察attributes變動時,是否需要記錄變動前的屬性值。
    • characterDataOldValue:表示觀察characterData變動時,是否需要記錄變動前的值。
    • attributeFilter:表示需要觀察的特定屬性,比如["class","src"]。

disconnect

mutationObserver.disconnect()
Mutation Observerdisconnect()方法告訴觀察者停止觀察變動,可以通過調用其observe()方法來重用觀察者。

takeRecords

const mutationRecords = mutationObserver.takeRecords()
Mutation ObservertakeRecords()方法返回已檢測到但尚未由觀察者的回調函數處理的所有匹配DOM更改的列表,使變更隊列保持爲空。此方法最常見的使用場景是在斷開觀察者之前立即獲取所有未處理的更改記錄,以便在停止觀察者時可以處理任何未處理的更改。

示例

Mutation Observer的一個常用功能就是觀察DOM元素的大小變更,通常是主動resize造成了該元素的大小發生變化,所以需要觀察者來完成DOM元素大小變更的副作用。在這裏完成了一個簡單的示例,觀察了attributeschildList兩個屬性值,並在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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章