MutationObserver監(jiān)視對DOM?樹所做更改的功能妙用
前言
上一篇給大家講解了關(guān)于IntersectionObserver的使用。 這一篇給大家講解一下MutationObserver的使用。
使用場景
首先關(guān)于MutationObserver的作用就是監(jiān)視對DOM所做更改的能力,那么他的使用面就特別的廣泛了,比如組件的自適應(yīng),垃圾回收,還有就是在不支持prmose的場景下實現(xiàn)異步完成函數(shù),防止用戶用devtools工具修改一些樣式,如:通過修改css或刪除標簽去除圖片水印等。
當(dāng)然只要是設(shè)計到DOM變動的MutationObserver都能幫你一些忙。
書寫格式
老規(guī)矩還是先放鏈接MutationObserver - Web API 接口參考 | MDN (mozilla.org)
首先MutationObserver同樣也是監(jiān)聽一個Node節(jié)點,然后通過相關(guān)的配置項 設(shè)置監(jiān)聽的范圍,當(dāng)范圍內(nèi)的相關(guān)屬性發(fā)生變化,便會觸發(fā)MutationObserver的回調(diào)函數(shù)。
var observer = new MutationObserver(callback);
相關(guān)方法
observe
mutationObserver.observe(target[, options])
target即我們要監(jiān)聽的Node節(jié)點,options即為配置項。
options屬性有以下幾個(我寫的簡短一點,詳細請點擊鏈接看文檔):
- subtree : true, ----將會監(jiān)聽以 target為根節(jié)點的整個子樹。包括子樹中所有節(jié)點的屬性,而不僅僅是針對target。
- childList: true, ----監(jiān)聽 target 節(jié)點中發(fā)生的節(jié)點的新增與刪除(同時,如果 subtree 為 true,會針對整個子樹生效)。
- attributes : true,----觀察所有監(jiān)聽的節(jié)點屬性值的變化。默認值為 true,當(dāng)聲明了 attributeFilter或 attributeOldValue,默認 值則為 false。
- characterData : true,----監(jiān)聽聲明的target 節(jié)點上所有字符的變化,如果聲明了characterDataOldValue,默認值則為 false
- attributeOldValue : true,---記錄上一次被監(jiān)聽的節(jié)點的屬性變化。
- characterDataOldValue : true----當(dāng)為 true 時,記錄前一個被監(jiān)聽的節(jié)點中發(fā)生的文本變化。
disconnect()
mutationObserver.disconnect()
disconnect方法告訴觀察者停止觀察變動??梢酝ㄟ^調(diào)用其 observe() 方法來重用觀察者。()意思就是停止監(jiān)聽)
takeRecords
mutationRecords = mutationObserver.takeRecords()
takeRecords方法返回已檢測到但尚未由觀察者的回調(diào)函數(shù)處理的所有匹配 DOM 更改的列表,使變更隊列保持為空。此方法最常見的使用場景是在斷開觀察者之前立即獲取所有未處理的更改記錄,以便在停止觀察者時可以處理任何未處理的更改。
MutationRecord對象
DOM每次發(fā)生變化,就會生成一條變動記錄(MutationRecord實例)。該實例包含了與變動相關(guān)的所有信息。MutationObserver處理的就是一個個MutationRecord實例組成的數(shù)組。
MutationRecord包含了Dom的有關(guān)信息,有以下屬性:
- type:觀察變動的類型,即原因(attribute、characterData或者childList等)
- target : 發(fā)生變動的DOM節(jié)點
- addedNodes :返回新增的DOM節(jié)點,如果沒有則為空(null)。
- removedNodes : 返回刪除的DOM節(jié)點,如果沒有則為空(null)。
- previousSibling :返回被添加或移除的節(jié)點之前的兄弟節(jié)點,或者 null。即上一個兄弟節(jié)點
- nextSibling : 返回被添加或移除的節(jié)點之后的兄弟節(jié)點,或者 null。即下一個兄弟節(jié)點
- attributeName:返回被修改的屬性的屬性名,或者 null。
- oldValue:這個屬性只對attribute和characterData變動生效,如果發(fā)生childList變動,則返回null。
案例
一、
去除水印的操作(這里只講下原理、概念),原理就是通過監(jiān)聽節(jié)點的屬性和后代節(jié)點和屬性,來實現(xiàn)無法去除的效果,簡單案例
// 選擇需要觀察變動的節(jié)點 const ul = document.querySelector('ul'); // 觀察器的配置(需要觀察什么變動) const config = { 'childList': true, 'subtree': true ,'attributes':true}; // 當(dāng)觀察到變動時執(zhí)行的回調(diào)函數(shù) const callback = function(mutationsList, observer) { console.log(111); console.log(mutationsList,observer); }; // 創(chuàng)建一個觀察器實例并傳入回調(diào)函數(shù) const observer = new MutationObserver(callback); // 以上述配置開始觀察目標節(jié)點 observer.observe(ul, config); const btn =document.querySelector('button') console.log(li); btn.addEventListener('click',()=>{ ul.style.background='pink' }) // // 之后,可停止觀察 // observer.disconnect();
無論我通過控制臺去刪除 ul中的li(子代)標簽還是改變ul的相關(guān)屬性或li(子代)的屬性 或者添加li操作。MutationObserver根據(jù)配置項監(jiān)聽,觸發(fā)回調(diào)函數(shù)。這也就是為什么通過一些方法想去去除水印。會發(fā)現(xiàn)刪不掉的原因。
注:style樣式只有內(nèi)聯(lián)樣式才可以觸發(fā)。CSS選擇器是無法觸發(fā)的。
操作相關(guān)觸發(fā)結(jié)果:
二、
如面試題:異步完成一個函數(shù),并盡量將任務(wù)放在微任務(wù)中。 異步完成函數(shù)的原理,因為MutationObserver實例的callback回調(diào)函數(shù)與IntersectionObserver一樣都為異步,這是W3C規(guī)定的。而且回調(diào)函數(shù)為微任務(wù)。
此處characterData:true,對應(yīng)的就是節(jié)點字符發(fā)生變化。
function asyncRun(fun){ //如果瀏覽器支持promise if(typeof Promise !=='undefined'){ Promise.resolve().then(fun); //如果瀏覽器支持 MutationObserve }else if(typeof MutationObserver!== 'undefined'){ const observe =new MutationObserver(fun); const textNode=document.createTextNode('0'); observe.observe(textNode,{characterData:true,}); textNode.data='1' //都不支持則放入定時器 }else{ setTimeout(fun) } }
三、
在vue的nextTick源碼中也用到了MutationObserver來實現(xiàn)異步調(diào)度機制,同上面的面試題類似。
總結(jié)
在我們?nèi)粘i_發(fā)中,可以用到MutationObserver的地方是特別特別多的。這是一個必會的技巧,我這里只是寫了一些基礎(chǔ)用法,大家還是要多看文檔多用才能夠靈活運用。
切記多看文檔?。?!
再放一遍鏈接,MutationObserver - Web API 接口參考 | MDN (mozilla.org)
以上就是MutationObserver監(jiān)視對DOM 樹所做更改的功能妙用的詳細內(nèi)容,更多關(guān)于MutationObserver監(jiān)視DOM 樹更改的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ES6使用Set數(shù)據(jù)結(jié)構(gòu)實現(xiàn)數(shù)組的交集、并集、差集功能示例
這篇文章主要介紹了ES6使用Set數(shù)據(jù)結(jié)構(gòu)實現(xiàn)數(shù)組的交集、并集、差集功能,結(jié)合實例形式分析了ES6中Set數(shù)據(jù)結(jié)構(gòu)的相關(guān)函數(shù)與實現(xiàn)數(shù)組交集、并集、差集的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10詳解JS去重及字符串奇數(shù)位小寫轉(zhuǎn)大寫
本篇文章主要介紹了詳解JS去重及字符串奇數(shù)位小寫轉(zhuǎn)大寫 ,非常具有實用價值,需要的朋友可以參考下。2016-12-12小程序中使用css var變量(使js可以動態(tài)設(shè)置css樣式屬性)
這篇文章主要介紹了小程序中使用css var變量,使js可以動態(tài)設(shè)置css樣式屬性,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03詳解webpack import()動態(tài)加載模塊踩坑
這篇文章主要介紹了詳解webpack import()動態(tài)加載模塊踩坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07javascript如何使用函數(shù)random來實現(xiàn)課堂隨機點名方法詳解
這篇文章主要介紹了javascript如何使用函數(shù)random來實現(xiàn)課堂隨機點名方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07帶你領(lǐng)略O(shè)bject.assign()方法的操作方式
這篇文章主要介紹了帶你領(lǐng)略O(shè)bject.assign()方法的操作方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08如何在微信小程序?qū)崿F(xiàn)一個幸運轉(zhuǎn)盤小游戲
這篇文章主要給大家介紹了關(guān)于如何在微信小程序?qū)崿F(xiàn)一個幸運轉(zhuǎn)盤小游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04