简体   繁体   English

对DOM的变化做出反应:Mutation Observers,window.addEventListener(“onresize”,callback)还是CSS替代品?

[英]Reacting to changes in the DOM: Mutation Observers, window.addEventListener(“onresize”, callback) or CSS alternatives?

I'm trying to figure out the best way to react to changes in the DOM. 我试图找出对DOM变化做出反应的最佳方法。

I've read similar posts about this, such as this one and this one and neither of them make it explicitly clear when to use Mutation Observers and when to use window.addEventListener("onresize", callback) . 我读过有关这类似的帖子,比如这一个 ,这一个和他们既不使其明确清楚何时使用突变观察以及何时使用window.addEventListener("onresize", callback) Are Mutation Observers more efficient than window.addEventListener("onresize", callback) even if the resize event is throttled ? 即使resize事件受到限制 window.addEventListener("onresize", callback) Mutation Observers是否比window.addEventListener("onresize", callback)更有效?

I've included this under the CSS3 tag because it looks like there were, in 2012, some neat CSS tricks that triggered custom resize events and I was wondering if there have been any innovations since then. 我把它包含在CSS3标签下,因为看起来在2012年有一些巧妙的CSS技巧触发了自定义调整大小事件 ,我想知道从那以后是否有任何创新。

Those two are different tools to solve different problems. 这两个是解决不同问题的不同工具。 Mutation observers are used to react to the changes in DOM. 变异观察者用于对DOM的变化做出反应。 Say you want to write a javascript function that replaces one word into another on the whole page, without end user noticing anything. 假设您要编写一个javascript函数,在整个页面上将一个单词替换为另一个单词,而无需最终用户注意到任何内容。 You could use setInterval here, but there's a risk of "flashing" content as it loads from the server ( or asynchronous AJAX call), unless you set the interval to a very small value, in which case it becomes a very resource intensive solution. 你可以在这里使用setInterval,但是当它从服务器(或异步AJAX调用)加载时存在“闪烁”内容的风险,除非你将间隔设置为一个非常小的值,在这种情况下它会成为一个非常资源密集的解决方案。

So instead you could write a mutation observer, which would get called every time there's a change in the DOM, which includes the page rendering or javascript adding/removing/modifying HTML elements down the line. 因此,您可以编写一个变异观察器,每次DOM发生变化时都会调用它,包括页面渲染或javascript添加/删除/修改HTML元素。 A client-side A/B testing tool I once wrote used those to catch changes in DOM and process them in the fastest way possible. 我曾编写的客户端A / B测试工具使用它们来捕获DOM中的更改并以尽可能最快的方式处理它们。

Adding listener to onresize event does just that - it gets called when the browser window is resized, regardless of DOM state at that point. 将侦听器添加到onresize事件就是这样 - 在调整浏览器窗口大小时调用它,无论此时的DOM状态如何。 So these two are not really interchangeable. 所以这两者并不是真的可以互换。 Mutation observers can get quite "expensive" resource-wise on heavier pages, so you might have to implement throttling there. 变异观察者可以在较重的页面上获得相当“昂贵”的资源,因此您可能必须在那里实施限制。 What you need depends on the specific case that you're dealing with, no way to answer that for sure. 你需要什么取决于你正在处理的具体情况,没有办法肯定地回答这个问题。

Besides handling two entirely different and usually unrelated tasks, their timing is different. 除了处理两个完全不同且通常不相关的任务外,它们的时间也不同。

MutationObserver callback is executed as a microtask during current event when no changes have been painted on screen yet. MutationObserver回调在当前事件期间作为微任务执行, 此时尚未在屏幕上绘制任何更改。 Since Javascript is single-threaded, the callback execution blocks further DOM parsing and the entire JS engine, so you'd want to make it very fast (I'm afraid, most wrapper libraries aren't, because of their versatility) and avoid observing the entire document while a complex page is being loaded as the callback may be called hundreds of times with lots of addedNodes in each mutation. 由于Javascript是单线程的,回调执行会阻止进一步的DOM解析和整个JS引擎,所以你想要非常快(我担心,大多数包装库不是,因为它们的多功能性)并且避免在加载复杂页面时观察整个document ,因为回调可能被调用数百次,每个突变中有大量添加的节点。

Events ("resize" event included) are added to the internal event queue and are processed when the current event queue has been completely processed and changes painted. 事件 (包括“resize”事件)将添加到内部事件队列中,并在完成当前事件队列处理和绘制更改后进行处理。 For example, setTimeout(callback, 0) , which creates a normal event task , may postpone the callback execution during a complex page load for 100-1000ms. 例如,创建正常事件任务的 setTimeout(callback, 0)可能会在复杂页面加载期间推迟100-1000ms的回调执行。

So, use MutationObserver only if you really want to change something before it's painted to make your changes seamlessly integrated with the page. 因此,只有在您真正想要在绘制之前更改某些内容以使您的更改与页面无缝集成时,才使用MutationObserver。 And of course, MutationObserver will only catch a change if an actual html attribute value has been changed or a node added/removed/changed, not just a calculated width based on CSS rules. 当然,如果实际的html属性值已更改或添加/删除/更改了节点,MutationObserver将仅捕获更改,而不仅仅是基于CSS规则的计算宽度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM