前面有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()
—— 獲取尚未處理的變動記錄列表,表中記錄的是已經發生,但回調暫未處理的變動。
這些方法可以一起使用