You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在2000年,MutationEvents API 被引入。虽然很有用,但在 DOM中 的每一次更改都会触发改变事件,这同样会导致性能问题。现在 MutationEvents API 已经被弃用,很快现代浏览器将完全停止支持它。
CSS animations
另一个有点奇怪的选择是依赖 CSS 动画。这听起来可能有点令人困惑。基本上,我们的想法是创建一个动画,一旦元素被添加到 DOM 中,动画就会被触发。动画开始的那一刻,animationstart 事件将被触发:如果已经将事件处理程序附加到该事件,那么你将确切地知道元素何时被添加到 DOM 中。动画的执行时间周期应该很小,用户几乎看不到它。
var insertionListener = function(event) {
// Making sure that this is the animation we want.
if (event.animationName === "nodeInserted") {
console.log("Node has been inserted: " + event.target);
}
}
Web 应用程序在客户端变得越来越重,原因很多,例如需要更丰富的 UI 来容纳更复杂的应用程序提供的内容,实时计算等等。复杂性的增加使得在 Web 应用程序生命周期的每个给定时刻都很难知道 UI 的确切状态。
而当你在搭建某些框架或者库的时候,甚至会更加困难,例如,前者需要根据 DOM 来作出反应并执行特定的动作。
概述
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。
这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个
<li>
元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在1000
个段落都插入结束后才会触发,而且只触发一次。Mutation Observer有以下特点:
它等待所有脚本任务完成后,才会运行,即采用异步方式
它把 DOM 变动记录封装成一个数组进行处理,而不是一条条地个别处理 DOM 变动
它即可以观察发生在 DOM 节点的所有变动,也可以观察某一类变动
为什么要要监听 DOM?
在很多情况下,MutationObserver API 都可以派上用场。例如:
你希望通知 Web 应用程序访问者,他当前所在的页面发生了一些更改。
你正在开发一个新的 JavaScript 框架,需要根据 DOM 的变化动态加载 JavaScript 模块。
也许你正在开发一个所见即所得(WYSIWYG) 编辑器,试图实现撤消/重做功能。通过利用 MutationObserver API,你可以知道在任何给定的点上进行了哪些更改,因此可以轻松地撤消这些更改。
这些只是 MutationObserver 可以提供帮助的几个例子。
MutationObserver 用法
在应用程序中实现 MutationObserver 相当简单。你需要通过传入一个函数来创建一个 MutationObserver 实例,每当有变化发生,这个函数将会被调用。函数的第一个参数是变动数组,每个变化都会提供它的类型和已经发生的变化的信息。
这个被创建的对象有三个方法:
observe()
observe 方法用来启动监听,它接受两个参数。
下面的片段展示了如何开始启动监听(observe ):
现在,假设 DOM 中有一些非常简单的 div:
使用 JQuery 来移除这个 div 上的 class:
正如我们已经开始观察到的,在调用
mutationObserver.observe(…)
之后,将在控制台中看到相应 MutationRecord 的日志:这个是由移除
class
属性导致的变化。MutationRecord
对象包含了DOM的相关信息,有如下属性:最后,为了在任务完成后停止观察 DOM,可以执行以下操作:
现在,
MutationObserver
已经被广泛支持:备择方案
MutationObserver 在之前还没有的,那么在 MutationObserver 还没出现之前,开发者采用什么方案呢?
这是几个可用的其他选项:
轮询(Polling)
MutationEvents
CSS animations
轮询(Polling)
最简单和最简单的方法是轮询。使用浏览器
setInterval
方法,可以设置一个任务,定期检查是否发生了任何更改。当然,这种方法会显著降低web 应用程序/网站的性能。MutationEvents
在2000年,MutationEvents API 被引入。虽然很有用,但在 DOM中 的每一次更改都会触发改变事件,这同样会导致性能问题。现在 MutationEvents API 已经被弃用,很快现代浏览器将完全停止支持它。
CSS animations
另一个有点奇怪的选择是依赖 CSS 动画。这听起来可能有点令人困惑。基本上,我们的想法是创建一个动画,一旦元素被添加到 DOM 中,动画就会被触发。动画开始的那一刻,
animationstart
事件将被触发:如果已经将事件处理程序附加到该事件,那么你将确切地知道元素何时被添加到 DOM 中。动画的执行时间周期应该很小,用户几乎看不到它。首先,需要一个父级元素,我们在它的内部监听节点的插入:
为了得到节点插入的处理器,需要设置一系列的 keyframe 动画,当节点插入的时候,动画将会开始。
创建
keyfram
后,还需要把它放入你想监听的元素上,注意应设置很小的 duration 值 —— 它们将会减弱动画在浏览器上留下的痕迹。这会将动画添加到
container-element
的所有子节点。 动画结束时,将触发插入事件。我们需要一个 JavaScript 函数作为事件监听器。在函数中,必须进行初始的
event.animationName
检查以确保它是我们想要的动画。现在是时候为父级元素添加事件监听了:
浏览器对CSS动画的支持情况:
MutationObserver 比上述解决方案有许多优点。本质上,它涵盖了 DOM 中可能发生的每一个更改,并且在批量触发更改时,它的优化程度更高。最重要的是,所有主要的现代浏览器都支持 MutationObserver,还有一些使用引擎下 MutationEvents 的 polyfill。
原文:
https://blog.sessionstack.com/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
你的点赞是我持续分享好东西的动力,欢迎点赞!
####欢迎加入前端大家庭,里面会经常分享一些技术资源。
The text was updated successfully, but these errors were encountered: