MutationObserver監聽DOM結構變化

前面有IntersectionObserver觀察器實現頁面懶加載的功能,原理就是觀察dom是否進入視口。那麼如果不管是否可見或者要實現隨時監聽,則需要使用MutationObserver。

示例代碼:

 1 filterObserve: function(_id) {
 2         if ($("#"+_id+" form t-form-item").length<5) return null
 3         //選擇一個需要觀察的節點
 4         var targetNode = document.getElementById(_id);
 5      // var targetNode = document.getElementsByClassName('query-searchBox')[0]//多頁面
 6         // 設置observer的配置選項
 7         var config = { childList: true,attributes: false, subtree: true//, characterData: true
 8         };
 9 
10         // 當節點發生變化時的需要執行的函數
11         var callback = function(mutationsList, observer) {
12             for(var mutation of mutationsList) {
13                 if (mutation.type == 'childList') {
14                     // console.error('A child node has been added or removed.');
15                     // 已展開,直接不設最大高度(或者500)
16                     if ($(".searchBox-box .icon-retract")[0]) {
17                         $("#"+_id).css("max-height", 'unset')
18                     }
19                     else// 已摺疊,只計算第一行的高度
20                     if ($(".searchBox-box .icon-retractno")[0]) {
21                         var mHeight = 0
22                         $("#"+_id+" form t-form-item").each((index, el)=>{// TODO,待優化,提示文字內容變化的情況下,怎麼獲取到變化前的高度?變化後大,則不再遍歷;變化後小,則遍歷
23                             if ($(el).find('t-form-explain')[0] && index<4) {
24                                 mHeight = Math.max(mHeight, $(el).find('t-form-explain').height())
25                             }
26                         })
27                         $("#"+_id).css("max-height", 36+mHeight+'px')//$("#querySearchBox").height()
28                     }
29                 }
30             }
31         };
32 
33         // 創建一個observer示例與回調函數相關聯
34         var observer = new MutationObserver(callback);
35 
36         //使用配置文件對目標節點進行觀測
37         observer.observe(targetNode, config);
38         return observer
39     },
40     filterDisObserve: function(observer) {
41         if (observer) observer.disconnect();
42     }

背景:

監聽搜索框內的dom變化,以便動態調整框的高度。因爲有展開和摺疊的功能,所以使用動態調整高度的方案(也可以通過顯示或隱藏可摺疊區來控制,如此一來就不需要關心高度計算問題了,相對更加合理,後邊有該方案的改法)。

使用:

在頁面dom加載完成後建立觀察者,在頁面銷燬時進行註銷

1 ngAfterViewInit() {
2     // this.toggleFilter()
3     this.filterObserver = ngtpAdapt.filterObserve("querySearchBoxCommonList")
4   }
5   ngOnDestroy() {
6     ngtpAdapt.filterDisObserve(this.filterObserver)
7   }

方案二:

去除高度限制,在展開摺疊時控制第4項之後的表單元素的顯隱

 1 ngAfterViewInit() {
 2     this.toggleFilter()
 3     // this.filterObserver = ngtpAdapt.filterObserve("querySearchBoxCommonList")
 4   }
 5   // ngOnDestroy() {
 6   //   ngtpAdapt.filterDisObserve(this.filterObserver)
 7   // }
 8   toggleFilter() {
 9     ngtpAdapt.showHideFilter(this.showQueryMore=!this.showQueryMore)
10   }
1 showHideFilter: function(bol) {
2         $(".query-searchBox form t-form-item").each((index, el)=>{
3             if (index>3) {
4                 $(el)[bol?'show':'hide']()
5             }
6         })
7     }

 

補充:

config 是一個具有布爾選項的對象,該布爾選項表示“將對哪些更改做出反應”:

  • childList —— node 的直接子節點的更改,
  • subtree —— node 的所有後代的更改,
  • attributes —— node 的特性(attribute),
  • attributeFilter —— 特性名稱數組,只觀察選定的特性。
  • characterData —— 是否觀察 node.data(文本內容),

其他幾個選項:

  • attributeOldValue —— 如果爲 true,則將特性的舊值和新值都傳遞給回調(參見下文),否則只傳新值(需要 attributes 選項),
  • characterDataOldValue —— 如果爲 true,則將 node.data 的舊值和新值都傳遞給回調(參見下文),否則只傳新值(需要 characterData 選項)。

然後,在發生任何更改後,將執行“回調”:更改被作爲一個 MutationRecord 對象列表傳入第一個參數,而觀察器自身作爲第二個參數。

MutationRecord 對象具有以下屬性:

  • type —— 變動類型,以下類型之一:
    • "attributes":特性被修改了,
    • "characterData":數據被修改了,用於文本節點,
    • "childList":添加/刪除了子元素。
  • target —— 更改發生在何處:"attributes" 所在的元素,或 "characterData" 所在的文本節點,或 "childList" 變動所在的元素,
  • addedNodes/removedNodes —— 添加/刪除的節點,
  • previousSibling/nextSibling —— 添加/刪除的節點的上一個/下一個兄弟節點,
  • attributeName/attributeNamespace —— 被更改的特性的名稱/命名空間(用於 XML),
  • oldValue —— 之前的值,僅適用於特性或文本更改,如果設置了相應選項 attributeOldValue/characterDataOldValue

有一個方法可以停止觀察節點:

  • observer.disconnect() —— 停止觀察。

當我們停止觀察時,觀察器可能尚未處理某些更改。在種情況下,我們使用:

  • observer.takeRecords() —— 獲取尚未處理的變動記錄列表,表中記錄的是已經發生,但回調暫未處理的變動。

這些方法可以一起使用

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