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() —— 获取尚未处理的变动记录列表,表中记录的是已经发生,但回调暂未处理的变动。

这些方法可以一起使用

posted @ 2024-02-29 19:56  TheFirstDream  阅读(422)  评论(0编辑  收藏  举报