变更事件将从 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,因此这些事件一直是浏览器中许多崩溃和安全 bug 的根源。

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

为什么移除变更事件

对变更事件的支持因浏览器而异。有些事件(例如 DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument)仅在部分浏览器中受支持。对于其他事件,由于缺少任何商定的规范,特定行为会有所不同。不过,有个合理的问题是:既然这些任务已经“完成”,为何不将它们留在那里并且只会降低使用这些代码的网页的速度?答案分为两个部分。

首先,这些事件影响了网络平台的发展。随着网络的发展以及新 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 软件包中。

时间表和弃用试用信息

我们将于 2024 年 7 月 23 日从 Chrome 127 中移除所有用户* 的变更事件,并将其发布到稳定版。提前预告,这些活动将提前从 Canary 版、开发者版和 Beta 版中移除。

  • 如果您需要更多时间(2024 年 7 月以后)来迁移代码,可以使用弃用试用计划,让指定网站上的活动暂时重新启用。此外,还有一项名为 MutationEventsEnabled企业政策,其作用与企业用户类似。无论采用哪种方式,都可以根据需要额外提供大约九个月的迁移时间。