首页
Preview

JavaScript 的工作原理:使用 MutationObserver 跟踪 DOM 的变化

本系列文章的第10篇,专注于探索JavaScript及其构建组件。在识别和描述核心元素的过程中,我们也分享了一些在构建SessionStack时使用的经验法则,SessionStack是一个JavaScript工具,用于通过像素完美的会话重放来识别、可视化和重现Web应用程序中的错误。

如果你错过了之前的文章,可以在这里找到它们:

  • 引擎、运行时和调用栈概述
  • Google V8引擎内部详解+ 5个编写优化代码的技巧
  • 内存管理+如何处理4种常见的内存泄漏
  • 事件循环和异步编程的崛起+使用async/await进行更好编码的5种方法
  • WebSockets和HTTP/2的深入探讨+SSE的正确选择方法
  • 与WebAssembly的比较+在某些情况下,为什么使用WebAssembly比JavaScript更好
  • Web Workers的构建块+ 5种使用它们的情况
  • Service Workers、它们的生命周期和用例
  • Web Push通知的机制

Web应用程序在客户端越来越重,原因有很多,例如需要更丰富的UI来容纳更复杂的应用程序,实时计算等等。

增加的复杂性使得在Web应用程序的生命周期中的每个给定时刻知道UI的确切状态变得更加困难。

如果你正在构建某种框架或只是一个库,例如必须根据DOM做出反应并执行某些操作,则这变得更加困难。

概述

MutationObserver是现代浏览器提供的Web API,用于检测DOM中的更改。使用此API,可以监听新添加或删除的节点、属性更改或文本节点的文本内容更改。

为什么要这样做?

MutationObserver API非常实用的情况有很多。例如:

  • 你想通知你的Web应用程序访问者页面上发生了某些更改。
  • 你正在开发一个新的花哨JavaScript框架,该框架根据DOM更改动态加载JavaScript模块。
  • 你可能正在开发WYSIWYG编辑器,尝试实现撤消/重做功能。通过利用MutationObserver API,你可以知道在任何给定时刻进行了哪些更改,因此可以轻松地撤消它们。

这些只是MutationObserver可以提供帮助的几个例子。

如何使用MutationObserver

MutationObserver实现到你的应用程序中相当容易。你需要通过传递一个函数来创建一个MutationObserver实例,每次发生变化时都会调用该函数。函数的第一个参数是在单个批次中发生的所有变化的集合。每个变化提供其类型和发生的更改的信息。

创建的对象有三种方法:

  • observe-开始监听更改。接受两个参数-你要观察的DOM节点和一个设置对象
  • disconnect-停止监听更改
  • takeRecords-在调用回调之前返回最后一批更改。

以下代码片段显示如何开始观察:

现在,假设你在DOM中有一些非常简单的div

使用jQuery,你可以从该div中删除class属性:

由于我们已经开始观察,因此在调用mutationObserver.observe(...)之后,我们将在相应的MutationRecord的控制台中看到日志:

这是由删除class属性引起的变化。

最后,在完成工作后停止观察DOM,可以执行以下操作:如今,MutationObserver 得到了广泛的支持:

其他选择

然而,MutationObserver 并不是一直存在的。那么在 MutationObserver 出现之前,开发者是如何解决这个问题的呢?

有一些其他的选择:

  • 轮询
  • MutationEvents
  • CSS 动画

轮询

最简单、最不复杂的方式是轮询。使用浏览器的 setInterval WebAPI,你可以设置一个任务,定期检查是否发生了任何变化。当然,这种方法会显著降低 Web 应用程序/网站的性能。

MutationEvents

在 2000 年,MutationEvents API 被引入。虽然很有用,但变异事件会在 DOM 的每一次更改时触发,这会导致性能问题。现在 MutationEvents API 已被弃用,现代浏览器很快将停止支持它。

这是 MutationEvents 的浏览器支持情况:

CSS 动画

一种有些奇怪的替代方法是依赖于 CSS 动画。这可能听起来有点令人困惑。基本上,这个想法是创建一个动画,一旦一个元素被添加到 DOM 中,就会被触发。当动画开始时,animationstart 事件将被触发:如果你已经将事件处理程序附加到该事件上,你就会知道元素何时被添加到 DOM 中。动画的执行时间应该很短,以至于用户几乎看不到它。

首先,我们需要一个父元素,在其中监听节点插入:

为了获取节点插入的句柄,我们需要设置一系列 关键帧 动画,这些动画将在插入节点时开始:

关键帧创建完毕后,需要将动画应用于你想要监听的元素。请注意小的持续时间 - 它们会放松浏览器中的动画印记:

这将为 container-element 的所有子节点添加动画。当动画结束时,插入事件将被触发。

我们需要一个 JavaScript 函数来作为事件监听器。在函数内部,必须进行初始的 event.animationName 检查,以确保它是我们想要的动画。

现在是时候将事件监听器添加到父级上了:

这是 CSS 动画的浏览器支持情况:

MutationObserver 在上述解决方案中提供了许多优势。本质上,它涵盖了可能发生在 DOM 中的每一个变化,而且它更加优化,因为它批量触发更改。除此之外,MutationObserver 被所有主要现代浏览器支持,还有一些使用 MutationEvents 的 polyfill。

MutationObserverSessionStack 库中占据了中心位置。

一旦将 SessionStack 库集成到你的 Web 应用程序中,它就开始收集数据,如 DOM 更改、网络请求、异常、调试消息等,并将其发送到我们的服务器。SessionStack 使用这些数据来重新创建你的用户所发生的一切,并以与你的用户相同的方式显示你的产品问题。很多用户认为 SessionStack 记录了实际的视频 - 它并没有。记录实际视频非常耗费资源,而我们收集的少量数据非常轻量级,不会影响你的 Web 应用程序的用户体验和性能。

如果你想要 尝试 SessionStack,可以使用免费计划。

资源

译自:https://medium.com/sessionstack-blog/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
一个人玩
先找到想要的,然后出发

评论(0)

添加评论