成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

MutationObserver 監(jiān)聽 DOM 樹變化

psychola / 1151人閱讀

摘要:是用于代替作為觀察樹結(jié)構(gòu)發(fā)生變化時,做出相應(yīng)處理的。觸發(fā)回調(diào)前返回最新的批量變化。發(fā)生相應(yīng)變動時,不再調(diào)用回調(diào)函數(shù)。其中數(shù)組也會作為,觀察者初始化時的回調(diào)函數(shù)的第一個參數(shù)。如果為,則表示需要記錄變動前的屬性值。

MutationObserver 是用于代替 MutationEvents 作為觀察 DOM 樹結(jié)構(gòu)發(fā)生變化時,做出相應(yīng)處理的 API 。為什么要使用 MutationObserver 去代替 MutationEvents 呢,我們先了解一下 MutationEvents

MutationEvents

它簡單的用法如下:

document.getElementById("list").addEventListener(
  "DOMSubtreeModified",
  () => {
    console.log("列表中子元素被修改")
  },
  false
)
// Mutation 事件列表
DOMAttrModified // 監(jiān)聽元素的修改
DOMAttributeNameChanged
DOMCharacterDataModified
DOMElementNameChanged
DOMNodeInserted // 監(jiān)聽新增
DOMNodeRemoved // 監(jiān)聽刪除
DOMNodeInsertedIntoDocument
DOMSubtreeModified // 監(jiān)聽子元素的修改

其中 DOMNodeRemoved ,DOMNodeInsertedDOMSubtreeModified分別用于監(jiān)聽元素子項的刪除,新增,修改(包括刪除和新增),DOMAttrModified 是監(jiān)聽元素屬性的修改,并且能夠提供具體的修改動作。

Mutation Events 遇到的問題

IE9 不支持 MutationEvents。Webkit 內(nèi)核不支持 DOMAttrModified 特性,DOMElementNameChangedDOMAttributeNameChanged 在 Firefox 上不被支持。

性能問題 1. MutationEvents 是同步執(zhí)行的,它的每次調(diào)用,都需要從事件隊列中取出事件,執(zhí)行,然后事件隊列中移除,期間需要移動隊列元素。如果事件觸發(fā)的較為頻繁的話,每一次都需要執(zhí)行上面的這些步驟,那么瀏覽器會被拖慢。 2. MutationEvents 本身是事件,所以捕獲是采用的是事件冒泡的形式,如果冒泡捕獲期間又觸發(fā)了其他的 MutationEvents 的話,很有可能就會導(dǎo)致阻塞 Javascript 線程,甚至導(dǎo)致瀏覽器崩潰。

Mutation Observer

MutationObserver 是在 DOM4 中定義的,用于替代 MutationEvents 的新 API,它的不同于 events 的是,所有監(jiān)聽操作以及相應(yīng)處理都是在其他腳本執(zhí)行完成之后異步執(zhí)行的,并且是所以變動觸發(fā)之后,將變得記錄在數(shù)組中,統(tǒng)一進(jìn)行回調(diào)的,也就是說,當(dāng)你使用 observer 監(jiān)聽多個 DOM 變化時,并且這若干個 DOM 發(fā)生了變化,那么 observer 會將變化記錄到變化數(shù)組中,等待一起都結(jié)束了,然后一次性的從變化數(shù)組中執(zhí)行其對應(yīng)的回調(diào)函數(shù)。

特點

所有腳本任務(wù)完成后,才會運行,即采用異步方式

DOM 變動記錄封裝成一個數(shù)組進(jìn)行處理,而不是一條條地個別處理 DOM 變動。

可以觀察發(fā)生在 DOM 節(jié)點的所有變動,也可以觀察某一類變動

目前,F(xiàn)irefox(14+)、Chrome(26+)、Opera(15+)、IE(11+) 和 Safari(6.1+) 支持這個 API。 Safari 6.0 和 Chrome 18-25 使用這個 API 的時候,需要加上 WebKit 前綴(WebKitMutationObserver)??梢允褂孟旅娴谋磉_(dá)式檢查瀏覽器是否支持這個 API。

const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
// 監(jiān)測瀏覽器是否支持
const observeMutationSupport = !!MutationObserver
如何使用 MutationObserver

在應(yīng)用中集成 MutationObserver 是相當(dāng)簡單的。通過往構(gòu)造函數(shù) MutationObserver 中傳入一個函數(shù)作為參數(shù)來初始化一個 MutationObserver 實例,該函數(shù)會在每次發(fā)生 DOM 發(fā)生變化的時候調(diào)用。MutationObserver 的函數(shù)的第一個參數(shù)即為單個批處理中的 DOM 變化集。每個變化包含了變化的類型和所發(fā)生的更改。

const mutationObserver = new MutationObserver(mutations => {
  mutations.forEach(mutation => {
    console.log(mutation)
  })
})

創(chuàng)建的實例對象擁有三個方法:

observe -開始進(jìn)行監(jiān)聽。接收兩個參數(shù)-要觀察的 DOM 節(jié)點以及一個配置對象。

disconnect -停止監(jiān)聽變化。

takeRecords -觸發(fā)回調(diào)前返回最新的批量 DOM 變化。

observer 方法

observer 方法指定所要觀察的 DOM 元素,以及要觀察的特定變動。

const article = document.querySelector("article")
observer.observer(article, {
  childList: true,
  arrtibutes: true
})

上面代碼分析:

指定所要觀察的 DOM 元素 article

指定所要觀察的變動是子元素的變動和屬性變動。

將這兩個限定條件作為參數(shù),傳入observer 對象 observer方法。

disconnect 方法

disconnect 方法用來停止觀察。發(fā)生相應(yīng)變動時,不再調(diào)用回調(diào)函數(shù)。

const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
// 選擇目標(biāo)節(jié)點
const target = document.querySelector("#some-id")
// 創(chuàng)建觀察者對象
const observer = new MutationObserver(mutation =>  {
  mutations.forEach(function(mutation) {
    console.log(mutation.type)
  })
})
// 配置觀察選項:
const config = { attributes: true, childList: true, characterData: true }
// 傳入目標(biāo)節(jié)點和觀察選項
observer.observe(target, config)
// 隨后,你還可以停止觀察
observer.disconnect()
takeRecord 方法

takeRecord 方法用來清除變動記錄,即不再處理未處理的變動。

在觀察者對象上調(diào)用 takeRecords 會返回 其觀察節(jié)點上的變化記錄(MutationRecord)數(shù)組。其中 MutationRecord 數(shù)組也會作為,觀察者初始化時的回調(diào)函數(shù)的第一個參數(shù)。

其包含的屬性如下:

type 如果是屬性發(fā)生變化,則返回 attributes.如果是一個CharacterData 節(jié)點發(fā)生變化,則返回 characterData ,如果是目標(biāo)節(jié)點的某個子節(jié)點發(fā)生了變化,則返回 childList .

target 返回此次變化影響到的節(jié)點,具體返回那種節(jié)點類型是根據(jù) type 值的不同而不同的,如果 type 為 attributes ,則返回發(fā)生變化的屬性節(jié)點所在的元素節(jié)點,如果 type 值為 characterData ,則返回發(fā)生變化的這個 characterData 節(jié)點.如果 type 為 childList ,則返回發(fā)生變化的子節(jié)點的父節(jié)點.

addedNodes 返回被添加的節(jié)點

removedNodes 返回被刪除的節(jié)點

previousSibling 返回被添加或被刪除的節(jié)點的前一個兄弟節(jié)點

nextSibling 返回被添加或被刪除的節(jié)點的后一個兄弟節(jié)點

attributeName 返回變更屬性的本地名稱

oldValue 根據(jù) type 值的不同,返回的值也會不同.如果 type 為 attributes,則返回該屬性變化之前的屬性值.如果 type 為 characterData,則返回該節(jié)點變化之前的文本數(shù)據(jù).如果 type 為 childList,則返回 null

observer.takeRecord()
MutationObserver 類型

MutationObserver 所觀察的 DOM 變動(即上面代碼的 option 對象),包含以下類型:

childList:子元素的變動

attributes:屬性的變動

characterData:節(jié)點內(nèi)容或節(jié)點文本的變動

subtree:所有下屬節(jié)點(包括子節(jié)點和子節(jié)點的子節(jié)點)的變動

想要觀察哪一種變動類型,就在 option 對象中指定它的值為 true。
需要注意的是,不能多帶帶觀察 subtree 變動,必須同時指定 childList、attributes 和 characterData 中的一種或多種。

除了變動類型,option 對象還可以設(shè)定以下屬性:

attributeOldValue:值為 true 或者為 false。如果為 true,則表示需要記錄變動前的屬性值。

characterDataOldValue:值為 true 或者為 false。如果為 true,則表示需要記錄變動前的數(shù)據(jù)值。

attributesFilter:值為一個數(shù)組,表示需要觀察的特定屬性(比如["class", "str"])。

創(chuàng)建 MutationObserver 并 獲取 dom 元素,定義回調(diào)數(shù)據(jù)。

// 獲取MutationObserver,兼容低版本的瀏覽器
const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
// 獲取dom元素
const list = document.querySelector("ol")
// 創(chuàng)建Observer
const Observer = new MutationObserver((mutations, instance) => {
  console.log(mutations)
  console.log(instance)
  mutations.forEach(mutation => {
    console.log(mutation)
  })
})

子元素的變動

Observer.observe(list, {
  childList: true,
  subtree: true
})
// 追加div標(biāo)簽
list.appendChild(document.createElement("div"))
// 追加文本
list.appendChild(document.createTextNode("foo"))
// 移除第一個節(jié)點
list.removeChild(list.childNodes[0])
// 子節(jié)點移除創(chuàng)建的div
list.childNodes[0].appendChild(document.createElement("div"))

監(jiān)測 characterData 的變動

Observer.observe(list, {
  childList: true,
  characterData: true,
  subtree: true
})
// 將第一個子節(jié)點的數(shù)據(jù)改為cha
list.childNodes[0].data = "cha"

監(jiān)測屬性的變動

Observer.observe(list, {
  attributes: true
})
// 設(shè)置節(jié)點的屬性  會觸發(fā)回調(diào)函數(shù)
list.setAttribute("data-value", "111")
// 重新設(shè)置屬性 會觸發(fā)回調(diào)
list.setAttribute("data-value", "2222")
// 刪除屬性 也會觸發(fā)回調(diào)
list.removeAttribute("data-value")

屬性變動前,記錄變動之前的值

Observer.observe(list, {
  attributes: true,
  attributeOldValue: true
})
// 設(shè)置節(jié)點的屬性  會觸發(fā)回調(diào)函數(shù)
list.setAttribute("data-value", "111")
// 刪除屬性
list.setAttribute("data-value", "2222")

characterData 變動時,記錄變動前的值。

Observer.observe(list, {
  childList: true,
  characterData: true,
  subtree: true,
  characterDataOldValue: true
})
// 設(shè)置數(shù)據(jù) 觸發(fā)回調(diào)
list.childNodes[0].data = "aaa"
// 重新設(shè)置數(shù)據(jù) 重新觸發(fā)回調(diào)
list.childNodes[0].data = "bbbb"

attributeFilter {Array} 表示需要觀察的特定屬性 比如 ["class", "src"];

Observer.observe(list, {
  attributes: true,
  attributeFilter: ["data-value"]
})
// 第一次設(shè)置屬性 data-key 不會觸發(fā)的,因為data-value 不存在
list.setAttribute("data-key", 1)
// 第二次會觸發(fā)
list.setAttribute("data-value", 1)
案例分析—demo 編輯器

下面我們做一個簡單的 demo 編輯器:

首先給父級元素 ol 設(shè)置 contenteditable 讓容器可編輯;

然后構(gòu)造一個 observer 監(jiān)聽子元素的變化;

每次回車的時候,控制臺輸出它的內(nèi)容;

  1. 111111
const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
const list = document.querySelector("ol")
const Observer = new MutationObserver((mutations, instance) => {
  mutations.forEach(mutation => {
    if (mutation.type === "childList") {
      const list_values = [].slice
        .call(list.children)
        .map(node => node.innerHTML)
        .filter(s => s !== "
") console.log(list_values) } }) }) Observer.observe(list, { childList: true })

現(xiàn)在我們繼續(xù)可以做一個類似于 input 和 textarea 中的 valueChange 的事件一樣的,監(jiān)聽值變化,之前的值和之后的值,如下代碼:

const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
const list = document.querySelector("ol")
const Observer = new MutationObserver((mutations, instance) => {
  mutations.forEach(mutation => {
    const enter = {
      mutation: mutation,
      el: mutation.target,
      newValue: mutation.target.textContent,
      oldValue: mutation.oldValue
    }
    console.log(enter)
  })
})

Observer.observe(list, {
  childList: true,
  attributes: true,
  characterData: true,
  subtree: true,
  characterDataOldValue: true
})
注意: 對 input 和 textarea 不起作用的。
案例分析—編輯器統(tǒng)計字?jǐn)?shù)

還可以輸入100字

const MutationObserver =
  window.MutationObserver ||
  window.WebKitMutationObserver ||
  window.MozMutationObserver
const editor = document.querySelector("#editor")
const textInput = document.querySelector("#textInput")
const observer = new MutationObserver(mutations => {
  mutations.forEach(function(mutation) {
    if (mutation.type === "characterData") {
      const newValue = mutation.target.textContent
      textInput.innerHTML = `還可以輸入${1000 - newValue.length}字`
    }
  })
})
observer.observe(editor, {
  childList: true,
  attributes: true,
  characterData: true,
  subtree: true,
  characterDataOldValue: true
})

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/100827.html

相關(guān)文章

  • VueJS源碼學(xué)習(xí)——MutationObserver實現(xiàn)nextTick

    摘要:倡導(dǎo)開發(fā)者盡量不直接操作,但有的時候由于各種需求讓開發(fā)者不得不這樣做,于是的實現(xiàn)就是讓開發(fā)者在修改數(shù)據(jù)后,能夠在數(shù)據(jù)更新到后才執(zhí)行對應(yīng)的函數(shù),從而獲取最新的數(shù)據(jù)。 Vue 倡導(dǎo)開發(fā)者盡量不直接操作 DOM,但有的時候由于各種需求讓開發(fā)者不得不這樣做,于是 nextTick 的實現(xiàn)就是讓開發(fā)者在修改數(shù)據(jù)后,能夠在數(shù)據(jù)更新到 DOM 后才執(zhí)行對應(yīng)的函數(shù),從而獲取最新的 DON 數(shù)據(jù)。 原文...

    xumenger 評論0 收藏0
  • JavaScript 工作原理之十-使用 MutationObserver 監(jiān)測 DOM 變化

    摘要:概述是現(xiàn)代瀏覽器提供的用來檢測變化的網(wǎng)頁接口。比如通知用戶當(dāng)前所在的頁面所發(fā)生的一些變化。觸發(fā)回調(diào)前返回最新的批量變化。在函數(shù)內(nèi)部,開始必須使用代碼進(jìn)行檢查,確保是我們所監(jiān)聽的動畫。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十章。 網(wǎng)絡(luò)應(yīng)用...

    bbbbbb 評論0 收藏0
  • JavaScript 工作原理之十-使用 MutationObserver 監(jiān)測 DOM 變化

    摘要:概述是現(xiàn)代瀏覽器提供的用來檢測變化的網(wǎng)頁接口。比如通知用戶當(dāng)前所在的頁面所發(fā)生的一些變化。觸發(fā)回調(diào)前返回最新的批量變化。在函數(shù)內(nèi)部,開始必須使用代碼進(jìn)行檢查,確保是我們所監(jiān)聽的動畫。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十章。 網(wǎng)絡(luò)應(yīng)用...

    zone 評論0 收藏0
  • JavaScript 工作原理之十-使用 MutationObserver 監(jiān)測 DOM 變化

    摘要:概述是現(xiàn)代瀏覽器提供的用來檢測變化的網(wǎng)頁接口。比如通知用戶當(dāng)前所在的頁面所發(fā)生的一些變化。觸發(fā)回調(diào)前返回最新的批量變化。在函數(shù)內(nèi)部,開始必須使用代碼進(jìn)行檢查,確保是我們所監(jiān)聽的動畫。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十章。 網(wǎng)絡(luò)應(yīng)用...

    Richard_Gao 評論0 收藏0
  • 如何優(yōu)雅監(jiān)聽容器高度變化

    摘要:哈哈哈哈,以上純屬虛構(gòu),不過在最近項目中還真遇到過對容器監(jiān)聽高寬變化在使用或滾動插件,如果容器內(nèi)部元素有高度變化要去及時更新外部包裹容器,即調(diào)用方法。處理很簡單,只需在動畫停止事件觸發(fā)時監(jiān)聽高寬變化即可。 前言 老鳥:怎樣去監(jiān)聽 DOM 元素的高度變化呢?菜鳥:哈哈哈哈哈,這都不知道哦,用 onresize 事件鴨!老鳥扶了扶眼睛,空氣安靜幾秒鐘,菜鳥才晃過神來。對鴨,普通 DOM 元...

    hizengzeng 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<