DOM 規范中的 MutationObserver 接口

MutationObserver 接口

DOM規范中的 MutationObserver 接口可以在DOM被修改時異步執行回調。

使用MutationObserver可以觀察整個文檔、DOM樹的一部分或某個元素,元素屬性、字節點、文本等。

新引進的MutationObserver接口取代了已廢棄的MutationEvent。

MutationObserver 實例

MutationObserver實例通過調用MutationObserver構造函數并傳入一個回調函數創建。

新創建的MutationObserver實例,需要使用observe()方法與DOM進行關聯。

observe()

兩個必填參數:

要觀察的DOM節點

MutationObserveInit 對象

MutationObserveInit對象用于控制觀察哪些方面的變化,是一個鍵值對形式配置選項的字典。

回調與 MutationRecord

MutationObserver(構造函數)中的參數(回調函數),每個回調都會收到一個MutationRecord實例的數組(第一個參數),記錄發生了什么變化以及DOM的哪部分收到了影響。

因為回調執行之前可能同時發生多個滿足觀察條件的事件,所以每次執行回調都會傳入一個包含按順序入隊的MutationRecord實例的數組。

new MutationObserver(fn)

參數:回調函數fn。

回調函數fn的參數:

第一個參數:MutationRecord實例的數組

第二個參數:觀察變化的MutationObserver的實例

MutationObserver?的回調函數可以多次執行。每當觀察到 DOM 樹的變化時,回調函數就會被調用。這些變化包括但不限于節點的添加、刪除、屬性的更改等。

那么問題來了

本例中,為什么回調中的?console.log?只輸出了一次?

let ob = new MutationObserver(function () {console.log("%cbody attributes changed", "color: red; font-weight:bold;font-size: 20px;");
});
ob.observe(document.body, { attributes: true });
document.body.setAttribute("foo", "bar");
document.body.className = "newClass";

解答(來自通義靈碼)

1.MutationObserver 是異步執行的

  • MutationObserver?的回調是通過?微任務隊列(microtask queue)?異步觸發的。
  • 當你在短時間內連續修改 DOM 屬性時,瀏覽器會將這些變更合并為一個批次,并只調用一次回調函數

2.?屬性變更被合并處理

  • 在你的代碼中:

    document.body.setAttribute("foo", "bar"); document.body.className = "newClass";

    這兩個操作都是對?document.body?的屬性進行修改。
  • 因為它們在同一個事件循環中發生,所以?MutationObserver?只會收到一次“屬性變化”的通知,并觸發一次回調。

🧪 實驗驗證

如果你希望看到兩次日志輸出,可以使用?setTimeout?將這兩個修改分開到不同的事件循環中:

document.body.setAttribute("foo", "bar"); setTimeout(() => { document.body.className = "newClass"; }, 0);

這樣,MutationObserver?會在兩個獨立的 microtask 中檢測到兩次屬性變更,從而觸發兩次回調。


? 總結

現象原因
console.log?只輸出一次瀏覽器將多個 DOM 修改合并為一次變更通知,回調只執行一次
關鍵點說明
異步機制MutationObserver 使用微任務隊列處理回調
批量優化瀏覽器自動合并多次變更以提升性能
控制輸出次數可通過?setTimeout?或其他方式分隔變更事件

🛠? 建議改進代碼

// 分開兩次 DOM 操作,確保觸發兩次回調 document.body.setAttribute("foo", "bar"); setTimeout(() => { document.body.className = "newClass"; }, 0);

這樣就能在控制臺看到兩次?"body attributes changed"?的日志輸出。

再記錄一個通用示例

部分代碼來自夸克瀏覽器。

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>木木的學習筆記</title><style>#target {border: 1px solid black;padding: 10px;margin-top: 10px;}</style></head><body><div class="container"><div class="navBox"></div><p>MutationObserver 的回調函數可以多次執行。每當觀察到 DOM 樹的變化時,回調函數就會被調用。這些變化包括但不限于節點的添加、刪除、屬性的更改等。</p><p>測試</p><div id="target">這是一個目標元素。</div><br /><button onclick="changeText()">改變文本</button></div><script src="./js/nav.js"></script><script>//加載頁面導航var navObj = {title: "MutationObserver",chapter: "",section: "",part: "",};setNav(navObj);</script><script>// 選擇需要觀察變動的節點const targetNode = document.getElementById("target");// 配置觀察選項const config = { childList: true, subtree: true, attributes: true, characterData: true };// 創建一個回調函數,當觀察到DOM變動時會被調用const callback = function (mutationsList, observer) {console.log("DOM changed");for (let mutation of mutationsList) {if (mutation.type === "childList") {console.log("A child node has been added or removed.");} else if (mutation.type === "attributes") {console.log(`The ${mutation.attributeName} attribute was modified.`);} else if (mutation.type === "characterData") {console.log("Character data in the node has been changed.");}}};// 創建一個觀察器實例并傳入回調函數const observer = new MutationObserver(callback);// 開始觀察目標節點observer.observe(targetNode, config);// 函數用于改變目標元素的文本內容let count = 0;function changeText() {targetNode.textContent = `文本已被第 ${++count} 次改變!`;}</script></body>
</html>

這個示例中,每次修改都被記錄。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89195.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

3.7 小結

圖3-7-1點云可視化點云可視化工具就像是打開點云數據寶藏大門的鑰匙&#xff0c;能讓我們直觀地理解和分析這些復雜的數據。本章節&#xff0c;主要介紹了PCL、Open3D、Matplotlib、PCShow、VTK 這幾種點云可視化工具。PCL&#xff08;Point Cloud Library&#xff09;是專注于…

對稱二叉樹、二叉樹直徑

101. 對稱二叉樹 - 力扣&#xff08;LeetCode&#xff09; 法一&#xff1a;遞歸。 對于兩個對稱位置的節點L和R&#xff08;L在左子樹&#xff0c;R在右子樹&#xff09;&#xff0c;只有當L的左節點值R的右節點值且L的右節點值R的左節點值時&#xff0c;這棵二叉樹才有可能對…

Java多線程1

線程是操作系統能夠運行調度的最小單位&#xff0c;它包含在進程之中&#xff0c;是進程的實際運作單位多線程有三種實現方式線程實現方法1&#xff0c;繼承Thread類&#xff08;無返回值&#xff09;&#xff1a;1、繼承Thread2、重寫run方法&#xff08;線程要執行的代碼&…

云計算如何提高企業的數據安全性和隱私保護

在企業數字化轉型加速推進的今天&#xff0c;數據安全與隱私保護已成為決定企業生存發展的核心命題。云計算憑借其靈活的架構優勢&#xff0c;不僅重塑了企業資源管理模式&#xff0c;更在數據安全防護領域構建起多層次保障體系。以下從六大維度解析云計算如何為企業數據安全與…

GaussDB 數據庫架構師修煉(二)數據庫計算容量評估

1 計算資源容量評估主要流程 一般地是經過以下5個流程評估GaussDB的計算容量: 2 TPC-C基準測試介紹 1)TPC-C是業界常用的一套Benchmark 由TPC (Transaction Processing Performance Council)委員會制定發布,用于 評測數據庫的聯機交易處理(偏向OLTP)能力,測試結果數據…

開源 python 應用 開發(六)網絡爬蟲

最近有個項目需要做視覺自動化處理的工具&#xff0c;最后選用的軟件為python&#xff0c;剛好這個機會進行系統學習。短時間學習&#xff0c;需要快速開發&#xff0c;所以記錄要點步驟&#xff0c;防止忘記。 鏈接&#xff1a; 開源 python 應用 開發&#xff08;一&#xf…

flink sql讀hive catalog數據,將string類型的時間戳數據排序后寫入kafka,如何保障寫入kafka的數據是有序的

在 Flink SQL 中&#xff0c;要確保從 Hive 讀取的 STRING 類型時間戳數據排序后有序寫入 Kafka&#xff0c;需要結合 批處理模式、時間類型轉換、單分區寫入 和 Kafka 生產者配置。以下是完整解決方案&#xff1a; 一、核心解決方案 1. 批處理模式 全局排序 將作業設置為批處…

7.17 滑動窗口 |assign |memo

lcp56. memo優化tle或者改用bfsclass Solution {int m, n;int dx[4] {0, 0, 1, -1};int dy[4] {1, -1, 0, 0};public:int conveyorBelt(vector<string>& matrix, vector<int>& start, vector<int>& end) {int ret INT_MAX;m matrix.size();n…

統計功效是什么?

統計功效的通俗理解可以把“統計功效”想象成偵探破案的能力——它代表統計檢驗&#xff08;偵探&#xff09;在犯罪事實確實存在&#xff08;真實效應存在&#xff09;時&#xff0c;成功發現真相&#xff08;檢測出效應&#xff09;的概率。核心比喻假設你是一個偵探&#xf…

大語言模型(LLM)訓練的教師強制(Teacher Forcing)方法

大語言模型&#xff08;LLM&#xff09;在訓練時使用一種名為“教師強制&#xff08;Teacher Forcing&#xff09;”的方法&#xff0c;而不是它們在推理&#xff08;生成文本&#xff09;時使用的“自回歸&#xff08;Autoregressive&#xff09;”方法 。闡明關于LLM訓練的一…

歸一化與激活函數:深度學習的雙引擎

歸一化和激活函數區別 歸一化和激活函數是深度學習中兩個不同但又存在關聯的技術,前者聚焦于“數據分布的調整”,后者聚焦于“引入非線性與輸出轉換”。 Softmax 既可以被視為一種歸一化操作,也屬于激活函數 因為它同時滿足兩者的核心特征,只是從不同角度定義:從“輸出…

C# --- 單例類錯誤初始化 + 沒有釋放資源導致線程泄漏

C# --- 單例類錯誤初始化 沒有釋放資源導致線程泄漏Background原因分析問題一&#xff1a; 錯誤初始化&#xff08;使用了箭頭函數&#xff09;問題一&#xff1a; 沒有Dispose資源Background 背景: service A的其中一個Api會向mq發送消息問題&#xff1a;線上發現這個服務經常…

MySQL基礎學習之DML,DQL(二)

這里寫目錄標題一、DML1、INSERT語句1)、給指定列添加數據2)、給全部列添加數據3)、批量數據添加數據4)、操作2、UPDATE語句3、DELETE語句二、DQL1、單表查詢1&#xff09;查詢語法2&#xff09;查詢全部3&#xff09;查詢部分4&#xff09;條件查詢5&#xff09;聚合函數6&…

在 Linux 系統中實現 Spring Boot 程序自動啟動的最佳實踐

在實際部署 Spring Boot 項目的生產環境中&#xff0c;如何確保服務自動啟動&#xff08;如開機自動運行、宕機自動恢復&#xff09;是一項基礎而關鍵的運維能力。本文將系統介紹如何在 Linux 中將 Spring Boot 應用注冊為 systemd 服務&#xff0c;實現進程守護與自動啟動。&a…

如何建立項目團隊的自驅力文化?

建立項目團隊的自驅力文化&#xff0c;關鍵在于賦權機制、目標共創、持續反饋、內在激勵、價值認同。 其中&#xff0c;“目標共創”尤其重要。項目成員若未參與目標制定&#xff0c;僅被動接受任務&#xff0c;將很難激發責任感和參與熱情。反之&#xff0c;通過共創目標&…

【React Native】布局文件-底部TabBar

布局文件-底部tabBar 內容配置 export default function Layout() {return (<Tabs />); }默認會將布局文件是將與它在同一個目錄的所有文件&#xff0c;包括下級目錄的文件&#xff0c;全都配置成Tab了。&#xff1a; 這樣做顯然不對&#xff0c;正確的做法是 在app目…

CompareFace使用

CompareFace 使用 CompareFace 有三種服務&#xff0c;分別是人臉識別&#xff08;RECOGNITION&#xff09;、人臉驗證&#xff08;VERIFICATION&#xff09;、人臉檢測&#xff08;DETECTION&#xff09;。 人臉識別其實就是人臉身份識別(每張照片只有一個人臉)&#xff0c;…

APP測試之Monkey壓力測試

&#xff08;一&#xff09;Monkey簡介 Monkey意指猴子&#xff0c;頑皮淘氣。所以Monkey測試&#xff0c;顧名思義也就像猴子一樣在軟件上亂敲按鍵&#xff0c;猴子什么都不懂&#xff0c;就愛搗亂。 Monkey 是 Android SDK 自帶的命令行工具&#xff0c;它通過向系統發送偽…

時序大模型為時序數據庫帶來的變革與機遇

時序數據&#xff08;Time Series Data&#xff09;作為記錄系統狀態隨時間變化的重要數據類型&#xff0c;在物聯網、金融交易、工業監控等領域呈爆炸式增長。傳統時序數據庫專注于高效存儲和查詢時序數據&#xff0c;而時序大模型&#xff08;Time Series Foundation Models&…

深入核心:理解Spring Boot的三大基石:起步依賴、自動配置與內嵌容器

深入核心&#xff1a;理解Spring Boot的三大基石&#xff1a;起步依賴、自動配置與內嵌容器 摘要&#xff1a;在上一章&#xff0c;我們領略了Spring Boot帶來的革命性開發體驗。但魔法的背后&#xff0c;必有其科學的支撐。本章將帶你深入Spring Boot的內核&#xff0c;系統性…