摘要:概述是現代瀏覽器提供的用來檢測變化的網頁接口。比如通知用戶當前所在的頁面所發(fā)生的一些變化。觸發(fā)回調前返回最新的批量變化。在函數內部,開始必須使用代碼進行檢查,確保是我們所監(jiān)聽的動畫。
原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。
本系列持續(xù)更新中,Github 地址請查閱這里。
這是 JavaScript 工作原理的第十章。
網絡應用在客戶端日益復雜,這是由很多因素的造成的,比如需要更加豐富的界面交互以提供更加復雜的應用功能,實時計算等等。
網絡應用的日益復雜導致無法知曉其生命周期中指定時刻準確的交互界面狀態(tài)。
如果你正在構建一些框架或者一個庫,這會更加的困難,比如,你無法通過監(jiān)測 DOM 來響應并執(zhí)行一些特定的操作。
概述MutationObserver? 是現代瀏覽器提供的用來檢測 DOM 變化的網頁接口。你可以使用這個接口來監(jiān)聽新增或者刪除節(jié)點,屬性更改,或者文本節(jié)點的內容更改。
可以干點啥好呢?
你可以在以下幾種情況信手拈來 MutationObserver 接口。比如:
通知用戶當前所在的頁面所發(fā)生的一些變化。
通過使用一些很棒的 JavaScript 框架來根據 DOM 的變化來動態(tài)加載 JavaScript 模塊。
可能當你在開發(fā)一個所見即所得編輯器的時候,使用 MutationObserver 接口來收集任意時間點上的更改,從而輕松地實現撤消/重做功能。
這只是幾個 MutationObserver 的使用場景。
如何使用 MutationObserver在應用中集成 MutationObserver 是相當簡單的。通過往構造函數 MutationObserver 中傳入一個函數作為參數來初始化一個 MutationObserver 實例,該函數會在每次發(fā)生 DOM 發(fā)生變化的時候調用。MutationObserver 的函數的第一個參數即為單個批處理中的 DOM 變化集。每個變化包含了變化的類型和所發(fā)生的更改。
var mutationObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation); }); });
創(chuàng)建的實例對象擁有三個方法:
observe-開始進行監(jiān)聽。接收兩個參數-要觀察的 DOM 節(jié)點以及一個配置對象。
disconnect-停止監(jiān)聽變化。
takeRecords-觸發(fā)回調前返回最新的批量 DOM 變化。
以下為開始監(jiān)聽的代碼片段:
// 開始監(jiān)聽頁面根元素 HTML 變化。 mutationObserver.observe(document.documentElement, { attributes: true, characterData: true, childList: true, subtree: true, attributeOldValue: true, characterDataOldValue: true });
現在,假設你寫了一個簡單的 div 元素:
Simple div
可以使用 jQuery 來移除 div 的 class 屬性:
$("#sample-div").removeAttr("class");
當調用 mutationObserver.observe(…) 就可以開始監(jiān)聽 DOM 變化。
當每次發(fā)生 DOM 變化的時候,會打印出各個 MutationRecord 日志信息:
這一變化是由移除 class 屬性所引起的。
最后,如果想停止監(jiān)聽 DOM 變化可以使用如下方法:
// MutationObserver 停止監(jiān)聽 DOM 變化 mutationObserver.disconnect();
現在,MutationObserver 瀏覽器兼容情況很好:
替代方法然而,之前 MutationObserver 并沒有被廣泛使用。那么,當沒有 MutationObserver 的時候,開發(fā)者是如何解決監(jiān)聽 DOM 變化的呢?
有幾下幾種可用的方法:
輪詢
MutationEvents
CSS 動畫
輪詢最簡單且粗糙的方法即使用輪詢。使用瀏覽器內置的 setInterval 網頁接口你可以創(chuàng)建一個定時任務來定時檢查 DOM 的變化。當然了,這個方法會顯著地減弱網絡應用/網站的性能。
其實,這是可以理解為臟檢查,如果有使用過 AngularJS 應該會有看過其臟檢查所導致的性能問題。在我的另一個系列里面有稍微介紹了下,具體可以查看這里。
MutationEvents早在 2000 年,就推出了 MutationEvents API 。雖然挺管用的,但是每個單一的 DOM 變化都會觸發(fā) mutation 事件,結果又會造成性能問題?,F在,MutationEvents 接口已經被廢棄,不久的將來,現代瀏覽器全都將停止支持該接口。
以下是 MutationEvents 的瀏覽器兼容情況:
CSS 動畫依靠 CSS 動畫 是一個有點令人感到新奇的替代方案。這聽起來會讓人有些困惑。大體上,實現思路是這樣的,創(chuàng)建一個動畫,一旦在 DOM 中添加一個元素就會觸發(fā)該動畫。開始執(zhí)行 CSS 動畫的時候就會觸發(fā) animationstart 事件:假設為該事件添加事件監(jiān)聽器,就可以準確知曉 DOM 中添加元素的時機。動畫的運行時間周期必須非常的短以便讓用戶感知不到,即體驗更佳。
首先,需要一個父級元素,在里面監(jiān)聽節(jié)點添加事件:
為了處理節(jié)點的添加,需要創(chuàng)建關鍵幀序列動畫,該序動畫在添加節(jié)點的時候啟動:
@keyframes nodeInserted { from { opacity: 0.99; } to { opacity: 1; } }
創(chuàng)建好關鍵幀之后,在需要監(jiān)聽的元素上應用動畫。注意到那個短暫的持續(xù)時間-在瀏覽器端動畫痕跡會非常平滑(即用戶會感覺不到有動畫發(fā)生):
#container-element * { animation-duration: 0.001s; animation-name: nodeInserted; }
這樣會為 container-element 的所有后代節(jié)點添加動畫。當動畫結束,觸發(fā) insertion 事件。
我們需要創(chuàng)建一個函數作為事件監(jiān)聽器。在函數內部,開始必須使用 event.animationName 代碼進行檢查,確保是我們所監(jiān)聽的動畫。
var insertionListener = function(event) { // 確保是所監(jiān)聽的動畫 if (event.animationName === "nodeInserted") { console.log("Node has been inserted: " + event.target); } }
為父元素綁定事件監(jiān)聽器:
document.addEventListener(“animationstart”, insertionListener, false); // standard + firefox document.addEventListener(“MSAnimationStart”, insertionListener, false); // IE document.addEventListener(“webkitAnimationStart”, insertionListener, false); // Chrome + Safari
這里采用了事件委托。
CSS 動畫瀏覽器支持情況:
相比以上幾種替代方案 MutationObserver 有幾點優(yōu)勢。本質上,它會監(jiān)聽 DOM 可能發(fā)生的每個變化并且性能更優(yōu),因其會批量 DOM 變化之后才觸發(fā)回調事件??傊?b>MutationObserver 的兼容性很好,并且還有一些墊片,這些墊片底層是基于 MutationEvents 的。
本系列持續(xù)更新中,Github 地址請查閱這里。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/108029.html
摘要:概述是現代瀏覽器提供的用來檢測變化的網頁接口。比如通知用戶當前所在的頁面所發(fā)生的一些變化。觸發(fā)回調前返回最新的批量變化。在函數內部,開始必須使用代碼進行檢查,確保是我們所監(jiān)聽的動畫。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十章。 網絡應用...
摘要:概述是現代瀏覽器提供的用來檢測變化的網頁接口。比如通知用戶當前所在的頁面所發(fā)生的一些變化。觸發(fā)回調前返回最新的批量變化。在函數內部,開始必須使用代碼進行檢查,確保是我們所監(jiān)聽的動畫。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十章。 網絡應用...
摘要:概觀是現代瀏覽器提供的,用于檢測中的變化。您可能正在使用所見即所得的編輯器,試圖實現撤銷重做功能。函數的第一個參數是在一個批次中發(fā)生的所有改變的集合。雖然有用,但中的每一次更改都會觸發(fā)突變事件,這又會導致性能問題。 showImg(https://segmentfault.com/img/bV9Z7q?w=1016&h=252);Web應用程序在客戶端越來越重要,原因很多,比如需要更豐...
摘要:觀察者模式介紹觀察者設計模式定義了對象間的一種一對多的依賴關系,以便一個對象的狀態(tài)發(fā)生變化時,所有依賴于它的對象都得到通知并自動刷新。 觀察者模式介紹 觀察者設計模式定義了對象間的一種一對多的依賴關系,以便一個對象的狀態(tài)發(fā)生變化時, 所有依賴于它的對象都得到通知并自動刷新。 一些好的文章觀察者模式與委托模式的區(qū)別深入理解JavaScript系列(32):設計模式之觀察者模式【Ja...
摘要:是用于代替作為觀察樹結構發(fā)生變化時,做出相應處理的。觸發(fā)回調前返回最新的批量變化。發(fā)生相應變動時,不再調用回調函數。其中數組也會作為,觀察者初始化時的回調函數的第一個參數。如果為,則表示需要記錄變動前的屬性值。 MutationObserver 是用于代替 MutationEvents 作為觀察 DOM 樹結構發(fā)生變化時,做出相應處理的 API 。為什么要使用 MutationObse...
閱讀 3428·2021-11-15 11:39
閱讀 1573·2021-09-22 10:02
閱讀 1318·2021-08-27 16:24
閱讀 3605·2019-08-30 15:52
閱讀 3418·2019-08-29 16:20
閱讀 832·2019-08-28 18:12
閱讀 558·2019-08-26 18:27
閱讀 726·2019-08-26 13:32