日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化

發(fā)布時(shí)間:2025/6/15 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

摘要: 掌握MutationObserver。

  • 原文:JavaScript是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化
  • 作者:前端小智

Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。

這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第10篇。

如果你錯(cuò)過了前面的章節(jié),可以在這里找到它們:

  • JavaScript 是如何工作的:引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述!
  • JavaScript 是如何工作的:深入V8引擎&編寫優(yōu)化代碼的5個(gè)技巧!
  • JavaScript 是如何工作的:內(nèi)存管理+如何處理4個(gè)常見的內(nèi)存泄漏 !
  • JavaScript 是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!
  • JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!
  • JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景 !
  • JavaScript 是如何工作的:Web Workers的構(gòu)建塊+ 5個(gè)使用他們的場景!
  • JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!
  • JavaScript 是如何工作的:Web 推送通知的機(jī)制!

Web 應(yīng)用程序在客戶端變得越來越重,原因很多,例如需要更豐富的 UI 來容納更復(fù)雜的應(yīng)用程序提供的內(nèi)容,實(shí)時(shí)計(jì)算等等。復(fù)雜性的增加使得在 Web 應(yīng)用程序生命周期的每個(gè)給定時(shí)刻都很難知道 UI 的確切狀態(tài)。

而當(dāng)你在搭建某些框架或者庫的時(shí)候,甚至?xí)永щy,例如,前者需要根據(jù) DOM 來作出反應(yīng)并執(zhí)行特定的動(dòng)作。

概述

Mutation Observer API 用來監(jiān)視 DOM 變動(dòng)。DOM 的任何變動(dòng),比如節(jié)點(diǎn)的增減、屬性的變動(dòng)、文本內(nèi)容的變動(dòng),這個(gè) API 都可以得到通知。

概念上,它很接近事件,可以理解為 DOM 發(fā)生變動(dòng)就會(huì)觸發(fā) Mutation Observer 事件。但是,它與事件有一個(gè)本質(zhì)不同:事件是同步觸發(fā),也就是說,DOM 的變動(dòng)立刻會(huì)觸發(fā)相應(yīng)的事件;Mutation Observer 則是異步觸發(fā),DOM 的變動(dòng)并不會(huì)馬上觸發(fā),而是要等到當(dāng)前所有 DOM 操作都結(jié)束才觸發(fā)。

這樣設(shè)計(jì)是為了應(yīng)付 DOM 變動(dòng)頻繁的特點(diǎn)。舉例來說,如果文檔中連續(xù)插入1000個(gè) <li>元素,就會(huì)連續(xù)觸發(fā)1000個(gè)插入事件,執(zhí)行每個(gè)事件的回調(diào)函數(shù),這很可能造成瀏覽器的卡頓;而 Mutation Observer 完全不同,只在 1000 個(gè)段落都插入結(jié)束后才會(huì)觸發(fā),而且只觸發(fā)一次。

Mutation Observer有以下特點(diǎn):

  • 它等待所有腳本任務(wù)完成后,才會(huì)運(yùn)行,即采用異步方式
  • 它把 DOM 變動(dòng)記錄封裝成一個(gè)數(shù)組進(jìn)行處理,而不是一條條地個(gè)別處理 DOM 變動(dòng)
  • 它即可以觀察發(fā)生在 DOM 節(jié)點(diǎn)的所有變動(dòng),也可以觀察某一類變動(dòng)

為什么要要監(jiān)聽 DOM?

在很多情況下,MutationObserver API 都可以派上用場。例如:

  • 你希望通知 Web 應(yīng)用程序訪問者,他當(dāng)前所在的頁面發(fā)生了一些更改。
  • 你正在開發(fā)一個(gè)新的 JavaScript 框架,需要根據(jù) DOM 的變化動(dòng)態(tài)加載 JavaScript 模塊。
  • 也許你正在開發(fā)一個(gè)所見即所得(WYSIWYG) 編輯器,試圖實(shí)現(xiàn)撤消/重做功能。通過利用 MutationObserver API,你可以知道在任何給定的點(diǎn)上進(jìn)行了哪些更改,因此可以輕松地撤消這些更改。

這些只是 MutationObserver 可以提供幫助的幾個(gè)例子。

MutationObserver 用法

在應(yīng)用程序中實(shí)現(xiàn) MutationObserver 相當(dāng)簡單。你需要通過傳入一個(gè)函數(shù)來創(chuàng)建一個(gè) MutationObserver 實(shí)例,每當(dāng)有變化發(fā)生,這個(gè)函數(shù)將會(huì)被調(diào)用。函數(shù)的第一個(gè)參數(shù)是變動(dòng)數(shù)組,每個(gè)變化都會(huì)提供它的類型和已經(jīng)發(fā)生的變化的信息。

var mutationObserver = new MutationObserver(function(mutations) {mutations.forEach(function(mutation) {console.log(mutation);}); });

這個(gè)被創(chuàng)建的對(duì)象有三個(gè)方法:

  • observe??— 啟動(dòng)監(jiān)聽
  • disconnect — 用來停止觀察
  • takeRecords?— 返用來清除變動(dòng)記錄,即不再處理未處理的變動(dòng)。

observe()

observe 方法用來啟動(dòng)監(jiān)聽,它接受兩個(gè)參數(shù)。

  • 第一個(gè)參數(shù):所要觀察的 DOM 節(jié)點(diǎn)
  • 第二個(gè)參數(shù):一個(gè)配置對(duì)象,指定所要觀察的特定變

下面的片段展示了如何開始啟動(dòng)監(jiān)聽(observe??):

// 開始偵聽頁面的根 HTML 元素中的更改。 mutationObserver.observe(document.documentElement, {attributes: true,characterData: true,childList: true,subtree: true,attributeOldValue: true,characterDataOldValue: true });

現(xiàn)在,假設(shè) DOM 中有一些非常簡單的 div:

<div id="sample-div" class="test"> Simple div </div>

使用 JQuery 來移除這個(gè) div 上的 class:

$("#sample-div").removeAttr("class");

正如我們已經(jīng)開始觀察到的,在調(diào)用 mutationObserver.observe(…) 之后,將在控制臺(tái)中看到相應(yīng) MutationRecord 的日志:

這個(gè)是由移除 class 屬性導(dǎo)致的變化。

MutationRecord 對(duì)象包含了DOM的相關(guān)信息,有如下屬性:

type:觀察的變動(dòng)類型(attribute、characterData或者childList)
target:發(fā)生變動(dòng)的 DOM 節(jié)點(diǎn)
addedNodes:新增的 DOM 節(jié)點(diǎn)
removedNodes:刪除的 DOM 節(jié)點(diǎn)
previousSibling:前一個(gè)同級(jí)節(jié)點(diǎn),如果沒有則返回 null
nextSibling:下一個(gè)同級(jí)節(jié)點(diǎn),如果沒有則返回 null
attributeName:發(fā)生變動(dòng)的屬性。如果設(shè)置了attributeFilter,則只返回預(yù)先指定的屬性。
oldValue:變動(dòng)前的值。這個(gè)屬性只對(duì) attribute 和 characterData 變動(dòng)有效,如果發(fā)生 childList 變動(dòng),則返回 null

最后,為了在任務(wù)完成后停止觀察 DOM,可以執(zhí)行以下操作:

mutationObserver.disconnect();

現(xiàn)在,MutationObserver 已經(jīng)被廣泛支持:

備擇方案

MutationObserver 在之前還沒有的,那么在 MutationObserver 還沒出現(xiàn)之前,開發(fā)者采用什么方案呢?

這是幾個(gè)可用的其他選項(xiàng):

  • 輪詢(Polling)
  • MutationEvents
  • CSS animations

輪詢(Polling)

最簡單和最簡單的方法是輪詢。使用瀏覽器 setInterval 方法,可以設(shè)置一個(gè)任務(wù),定期檢查是否發(fā)生了任何更改。當(dāng)然,這種方法會(huì)顯著降低web 應(yīng)用程序/網(wǎng)站的性能。

MutationEvents

在2000年,MutationEvents API 被引入。雖然很有用,但在 DOM中 的每一次更改都會(huì)觸發(fā)改變事件,這同樣會(huì)導(dǎo)致性能問題。現(xiàn)在 MutationEvents API 已經(jīng)被棄用,很快現(xiàn)代瀏覽器將完全停止支持它。

CSS animations

另一個(gè)有點(diǎn)奇怪的選擇是依賴 CSS 動(dòng)畫。這聽起來可能有點(diǎn)令人困惑。基本上,我們的想法是創(chuàng)建一個(gè)動(dòng)畫,一旦元素被添加到 DOM 中,動(dòng)畫就會(huì)被觸發(fā)。動(dòng)畫開始的那一刻,animationstart 事件將被觸發(fā):如果已經(jīng)將事件處理程序附加到該事件,那么你將確切地知道元素何時(shí)被添加到 DOM 中。動(dòng)畫的執(zhí)行時(shí)間周期應(yīng)該很小,用戶幾乎看不到它。

首先,需要一個(gè)父級(jí)元素,我們?cè)谒膬?nèi)部監(jiān)聽節(jié)點(diǎn)的插入:

<div id=”container-element”></div>

為了得到節(jié)點(diǎn)插入的處理器,需要設(shè)置一系列的 keyframe 動(dòng)畫,當(dāng)節(jié)點(diǎn)插入的時(shí)候,動(dòng)畫將會(huì)開始。

@keyframes nodeInserted { from { opacity: 0.99; }to { opacity: 1; } }

創(chuàng)建 keyfram 后,還需要把它放入你想監(jiān)聽的元素上,注意應(yīng)設(shè)置很小的 duration 值 —— 它們將會(huì)減弱動(dòng)畫在瀏覽器上留下的痕跡。

#container-element * {animation-duration: 0.001s;animation-name: nodeInserted; }

這會(huì)將動(dòng)畫添加到 container-element 的所有子節(jié)點(diǎn)。 動(dòng)畫結(jié)束時(shí),將觸發(fā)插入事件。

我們需要一個(gè) JavaScript 函數(shù)作為事件監(jiān)聽器。在函數(shù)中,必須進(jìn)行初始的 event.animationName 檢查以確保它是我們想要的動(dòng)畫。

var insertionListener = function(event) {// Making sure that this is the animation we want.if (event.animationName === "nodeInserted") {console.log("Node has been inserted: " + event.target);} }

現(xiàn)在是時(shí)候?yàn)楦讣?jí)元素添加事件監(jiān)聽了:

document.addEventListener(“animationstart”, insertionListener, false); // standard + firefox document.addEventListener(“MSAnimationStart”, insertionListener, false); // IE document.addEventListener(“webkitAnimationStart”, insertionListener, false); // Chrome + Safari

瀏覽器對(duì)CSS動(dòng)畫的支持情況:

MutationObserver 比上述解決方案有許多優(yōu)點(diǎn)。本質(zhì)上,它涵蓋了 DOM 中可能發(fā)生的每一個(gè)更改,并且在批量觸發(fā)更改時(shí),它的優(yōu)化程度更高。最重要的是,所有主要的現(xiàn)代瀏覽器都支持 MutationObserver,還有一些使用引擎下 MutationEvents 的 polyfill。

原文:

https://blog.sessionstack.com...

代碼部署后可能存在的BUG沒法實(shí)時(shí)知道,事后為了解決這些BUG,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具Fundebug。

你的點(diǎn)贊是我持續(xù)分享好東西的動(dòng)力,歡迎點(diǎn)贊!

一個(gè)笨笨的碼農(nóng),我的世界只能終身學(xué)習(xí)!

更多內(nèi)容請(qǐng)關(guān)注公眾號(hào)《大遷世界》!

關(guān)于Fundebug

Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,Fundebug累計(jì)處理了9億+錯(cuò)誤事件,付費(fèi)客戶有Google、360、金山軟件、百姓網(wǎng)等眾多品牌企業(yè)。歡迎大家[免費(fèi)試用]

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。