变更事件将从 Chrome 中移除

宣布弃用并计划移除变更事件,并分享了在 2024 年 7 月移除代码之前如何迁移代码。

Mason Freed
Mason Freed

Chromium 已正式弃用变更事件,并计划从版本 127 开始停止支持,该版本将于 2024 年 7 月 23 日进入稳定版。这篇博文说明了我们移除变更事件的原因,并提供了在从浏览器中移除变更事件之前进行迁移的路径。

什么是突变事件?

变更事件是以下事件集合的名称:

  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMSubtreeModified
  • DOMCharacterDataModified
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemovedFromDocument
  • (任何新型浏览器都不支持)DOMAttrModified
  • (任何新型浏览器都不支持)DOMAttributeNameChanged
  • (任何新型浏览器都不支持)DOMElementNameChanged

这些事件是 DOM 级别 2 规范中非常旧的部分,它们自 2011 年起被弃用。取而代之的是 MutationObserver 接口自 2013 年以来,所有现代浏览器都支持该接口

变更事件的历史记录

很久之前,突变事件听起来似乎是个好主意,但事实证明它存在几个严重缺陷

  • 此类代码过长,触发频率过高。系统会针对移除的每个节点分别触发一个事件。
  • 它们的运行速度很,原因在于事件传播,以及它们会阻止许多 UA 运行时优化。
  • 它们经常会导致崩溃。它们已成为导致浏览器许多崩溃和安全错误的原因,因为事件监听器可能会更改正在运行的 DOM 操作下的整个 DOM。

由于这些缺陷,这些事件已于 2011 年从规范中弃用,并于 2012 年构建了一个替代 API (MutationObserver)。到目前为止,这个新 API 已实施并正常运行了 10 多年。

为什么要移除突变事件

对变更事件的支持因浏览器而异。某些事件(例如 DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument)并非在所有浏览器中都受支持。对于其他事件,由于缺少任何商定的规范,特定行为会有所不同。然而,合理的问题可能是:为什么不将它们留在那里,因为这些网址是“完成”的,只会拖慢使用它们的网页的速度呢?答案分为两个部分。

首先,这些事件阻碍了 Web 平台的发展。随着网络的发展和新 API 的不断增加,必须考虑这些旧版 API 的存在。有时,只是需要支持这些事件可能会导致无法建议新的 API。例如,有一个长期的请求旨在阻止 <iframe> 元素在 DOM 内移动时重新加载。然而,部分原因是由于存在突变事件,该工作被认为难以实现,因此请求被关闭。

这些事件将继续妨碍浏览器提高速度。即使浏览器已采取这些优化措施来避免在未使用变更事件的网页上造成性能损失,也并非十全十美。对于突变事件监听器,仍需在许多位置进行检查。代码仍然需要非常防御性编写,因为这些事件可能会以令人惊讶的方式改变 DOM。

自这些事件正式弃用以来,已有 10 多年的时间,而替换 API 也同样可以使用 10 多年,现在终于来到最终从浏览器中彻底移除变更事件的时间了。

如何迁移

改用 MutationObserver

有关 MutationObserver 的文档位于 MDN 中,内容相当完整。代码库的替换取决于这些事件的使用方式,但举个例子:

// Old mutation event usage:  
target.addEventListener(‘DOMNodeInserted',event => doSomething(event.target));

// Replacement mutation observer code:  
const observer = new MutationObserver(mutationList =>  
  mutationList.filter(m => m.type === 'childList').forEach(m => {  
    m.addedNodes.forEach(doSomething);  
  }));  
observer.observe(target,{childList: true, subtree: true});  

虽然 MutationObserver 代码看起来比原始的 DOMNodeInserted 事件监听器代码大,但请注意,它可以在一次调用中处理对整个树发生的所有变更,而无需对事件处理脚本进行多次调用。

聚酯纤维

有一个 polyfill,它试图允许现有代码在由 MutationObserver 提供支持的同时继续运行。polyfill 位于 GitHub 上或以 npm 软件包的形式提供。

时间表和弃用试用信息

我们将从 Chrome 127 中为所有用户移除变更事件*,并于 2024 年 7 月 23 日升级为稳定版。我们很早就开始将这类活动从 Canary 版、开发者版和 Beta 版中移除,以提前进行预告。

  • 如果您需要更多时间(2024 年 7 月之后)迁移代码,可以通过弃用试用在特定网站上暂时重新启用这些活动。对于企业用户,还有一项名为 MutationEventsEnabled企业政策。如果需要,这两种方法都额外延长了大约九个月的迁移时间。