MutationObserve的使用和應用

MutationObserve的使用和應用

前言

最近接到一個項目需求,就是把另一個項目嵌入到當前項目中。要求很簡單,讓人看不出這是嵌入過來的。

本來覺得這也沒什麼,因爲以前也做過一次。

方案無非就是通過iframe嵌入,通過postMessage進行通信(ps:兩個項目都是我們自己的,可以修改代碼)。

其他的一切都ok,就有個一個問題困擾了。

我們當前的項目是一個典型的聖盃佈局,頭部和底部都要顯示內容。

而嵌入的頁面的高度是不固定的,如果固定iframe的高度,就會出現有的頁面過短導致iframe出現大片空白,有的頁面過長導致iframe會出現滾動條,

所以,我需要解決的是如何隨時獲知嵌入頁面的高度。

第一種方案——輪詢

我發現只要是聽到“隨時”兩個字,肯定有一個解決方案是輪詢,但肯定馬上又否決了這個方案。

沒辦法,降低程序性能的我們不要。

第二種方案——MutationObserve

第二種方案,就要請出我們今天的主角了,MutationObserve

這是個少爲人知的API,卻是被所有瀏覽器所支持(重點:ie11支持,ie11以下繞路,我們的項目只要支持ie11)。

使用

使用MutationObserve非常簡單。

首先,通過MutationObserve構造函數,創建一個實例。

var observer = new MutationObserve(function (mutation) {
    mutations.forEach(function(mutation) {
    console.log(mutation);
  });
})

構造函數的參數是一個回調函數,返會的參數是一個對象,屬性如下

type: 如果是屬性發生變化,則返回attributes.如果是一個CharacterData節點發生變化,則返回characterData,如果是目標節點的某個子節點發生了變化,則返回childList.
target: 返回此次變化影響到的節點,具體返回那種節點類型是根據type值的不同而不同的,如果type爲attributes,則返回發生變化的屬性節點所在的元素節點,如果type值爲characterData,則返回發生變化的這個characterData節點.如果type爲childList,則返回發生變化的子節點的父節點.
addedNodes: 返回被添加的節點
removedNodes: 返回被刪除的節點
previousSibling: 返回被添加或被刪除的節點的前一個兄弟節點
nextSibling: 返回被添加或被刪除的節點的後一個兄弟節點
attributeName: 返回變更屬性的本地名稱
oldValue: 根據type值的不同,返回的值也會不同.如果type爲attributes,則返回該屬性變化之前的屬性值.如果type爲characterData,則返回該節點變化之前的文本數據.如果type爲childList,則返回null

然後,通過實例的observe方法進行觀察目標dom

Observer.observe(targetNode, options)

// 代碼實例
var targetNode = document.body
var options = {
    childList: true,
    attributes: true,
    subtree: true
}
Observer.observe(targetNode, options)

observe方法接收連個參數

  • targetNode

    就是你需要觀察的DOM對象

  • options

    options是一個MutationObserverInit的對象,屬性如下

    childList: 設爲true以監視目標節點(如果subtree爲true,則包含子孫節點)添加或刪除新的子節點。默認值爲false。
    subtree: 設爲true以擴展監視範圍到目標節點下的整個子樹的所有節點
    attributes: 設爲true以觀察受監視元素的屬性值變更。默認值爲false。
    attributeOldValue: 在attributes屬性已經設爲true的前提下,當監視節點的屬性改動時,將此屬性設爲true 將記錄任何有改動的屬性的上一個值。
    attributeFilter: 要監視的特定屬性名稱的數組。如果未包含此屬性,則對所有屬性的更改都會觸發變動通知。無默認值。
    characterData: 設爲true以監視指定目標節點或子節點樹中節點所包含的字符數據的變化。無默認值。(一種抽象接口,具體可以爲文本節點,註釋節點,以及處理指令節點)時,也要觀察該節點的文本內容是否發生變化
    characterDataOldValue: 在characterData屬性已經設爲true的前提下,設爲true以在文本在受監視節點上發生更改時記錄節點文本的先前值
    

實例還有兩個方法

disconnect

終止在觀察者對象上設置的節點的變化監聽,直到重新調用observe方法

takeRecords

在回調被觸發前返回最後一批更改,就是說當你調用了disconnect方法,會返回最後一次的更改,而不直接終止了。

MutationsObserve是異步的,同Promise

應用

回到最初的需求,如何隨時獲知ifame嵌入的頁面的高度?

上代碼

var ele = document.documentElement
var oldHeight = null
var observer = new MutationObserve(function (mutation) {
	var newHeight = ele.height
	if (newHeight != oldHeight) {
		oldHeight = newHeight
		// 通過postMessage進行iframe之間的通信
		window.top.postMessage({
			type: 'IframeInnerHeight',
			height: newHeight
		}, '*')
	}
})
var options = {
	childList: true,
	subtree: true,
	attributes: true
}
observer.observe(ele, options)

當父級接收到頁面的高度就可重新設置Iframe的高度,這樣兩個項目就完美的融合一起了。

思考

當我們瞭解了MutationObserve的強大功能時,我們是否可以多想想,它還能做什麼?我們能依靠它來做什麼?

這裏推薦一篇文章,提供三個應用場景

Mutation Observer 的三個實際應用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章