Javascript MutationObserver检测整个DOM中节点的性能
我感兴趣的是使用Javascript MutationObserver检测整个DOM中节点的性能,javascript,html,mutation-observers,Javascript,Html,Mutation Observers,我感兴趣的是使用MutationObserver来检测HTML页面中是否添加了特定的HTML元素。例如,我要说的是,我想检测DOM中是否添加了任何 到目前为止,我看到的所有MutationObserver示例都只检测节点是否添加到特定容器中。例如: 一些HTML <body> ... <ul id='my-list'></ul> ... </body> 因此,在本例中,MutationObserver被设置为监视一个非常特定的
MutationObserver
来检测HTML页面中是否添加了特定的HTML元素。例如,我要说的是,我想检测DOM中是否添加了任何
到目前为止,我看到的所有MutationObserver
示例都只检测节点是否添加到特定容器中。例如:
一些HTML
<body>
...
<ul id='my-list'></ul>
...
</body>
因此,在本例中,MutationObserver
被设置为监视一个非常特定的容器(ul#my list
),以查看是否有任何
附加到它
如果我想不那么具体,并且像这样在整个HTML正文中观察
,这是一个问题吗:
var container = document.querySelector('body');
我知道它在我为自己设置的基本示例中有效。。。但不建议这样做吗?这是否会导致性能不佳?如果是这样,我将如何检测和衡量性能问题
我想可能是因为所有的MutationObserver
示例都非常特定于它们的目标容器。。。但我不确定。这个答案主要适用于大而复杂的页面。
如果在页面加载/呈现之前附加,如果页面很大且复杂(,),则未优化的MutationObserver回调可以为页面加载时间增加几秒钟(例如,5秒到7秒)。回调作为一个微任务执行,它会阻止DOM的进一步处理,并且在一个复杂的页面上每秒可以触发数百次或数千次。大多数示例和现有库都没有考虑到这种情况,并且提供了美观、易于使用但可能速度较慢的JS代码
.observe()中的属性过滤器:[attr1',attr2']
选项
子树:false
)。例如,通过递归观察
document
来等待父元素是有意义的,成功时断开观察者的连接,在此容器元素上附加一个新的非递归元素
id
属性的元素时,使用异常快速的getElementById
而不是枚举突变
数组(它可能有数千个条目):
iframe
或object
),请使用由getElementsByTagName
和getElementsByClassName
返回的live HTMLCollection,并重新检查所有元素,而不是枚举突变
,如果它有100多个元素,比如说
querySelector
,尤其是速度极慢的querySelector all
querySelectorAll
在MutationObserver回调中是绝对不可避免的,首先执行querySelector
检查,如果成功,继续执行querySelectorAll
。平均来说,这样的组合会快得多
for(var i=0…)
loop(慢10-100倍),而MutationObserver回调可能会在复杂的现代页面上报告数千个节点
- 即使在较旧的浏览器中,lodash或类似的fast库支持的替代函数枚举也可以
- 自2018年起,Chrome/ium内置了标准阵列方法
for(让v of something)
,除非您进行了传输,以便生成的代码与经典的for
循环一样快
setTimeout(fn,0)安排整个页面的重新检查和重新处理
:当解析/布局活动的初始突发完成时,引擎会“呼吸”,这可能需要一秒钟的时间。然后,您可以使用requestAnimationFrame不显眼地将页面分块处理
const queue=[];
const mo=新的突变观察者(突变=>{
如果(!queue.length)请求AnimationFrame(进程);
排队推送(突变);
});
函数过程(){
for(队列的常数突变){
// ..........
}
queue.length=0;
}
ul#my list
,查看是否有任何
附加到它
由于li
是一个直接的子节点,我们需要寻找添加的节点,因此唯一需要的选项是childList:true
(请参见上面的建议2)
性能问题是特定于给定场景的。如果您的整个文档只有几个简单的元素,我相信您不会有任何问题。如果您担心出现性能问题,请配置文件!我使用了大量的
MutationObserver
s,让它们递归地监视整个DOM。我个人从来没有
var container = document.querySelector('body');
new MutationObserver(function(mutations, observer) {
// Do something here
// Stop observing if needed:
observer.disconnect();
}).observe(document.querySelector('ul#my-list'), {childList: true});