变更事件将从 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 运行时优化,因此它们的速度较慢
  • 它们经常会导致崩溃。它们是浏览器中许多崩溃和安全 bug 的根源,因为事件监听器可以更改正在运行的 DOM 操作下的整个 DOM。

由于存在这些缺陷,这些事件在 2011 年被废弃,并在 2012 年构建了替代 API (MutationObserver)。新 API 已实施并投入使用超过 10 年。

变更事件被移除的原因

对更改事件的支持因浏览器而异。某些事件(例如 DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument)在某些浏览器中不受支持。对于其他事件,由于缺少任何商定的规范,具体行为会有所不同。不过,一个合理的问题可能是:既然这些资源已“完成”,并且只会降低使用它们的网页的速度,为什么不直接保留它们?答案分为两部分。

首先,这些事件会拖慢 Web 平台的速度。随着 Web 技术不断发展,我们会添加新的 API,但也必须考虑这些旧版 API 的存在。有时,仅仅需要支持这些事件,就可能导致无法提议新 API。例如,有一个长期存在的请求,旨在防止 <iframe> 元素在 DOM 中移动时重新加载。不过,部分由于存在突变事件,我们认为实现该功能的难度太高,因此关闭了该请求。

这些事件仍然会妨碍浏览器的加速。即使浏览器进行了优化(试图避免在未使用更改事件的网页上出现性能下降),但效果也不尽如人意。仍需要在许多地方对 Mutation 事件监听器进行检查。由于这些事件可能会以意想不到的方式更改 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

有一个 polyfill 会尝试让现有代码在由 MutationObserver 提供支持的情况下继续运行。该 polyfill 位于 GitHub 上,或以 npm 软件包的形式提供。

时间表和弃用试用版信息

我们将从 Chrome 127 中移除基因突变事件,该版本将于 2024 年 7 月 23 日发布为稳定版,届时所有用户都将无法再使用该事件。为提前提醒,我们将于 2020 年 12 月 31 日之前从 Canary、Dev 和 Beta 版渠道中移除这些事件。

  • 如果您需要更多时间(超过 2024 年 7 月)来迁移代码,可以使用弃用试用版,该试用版会在指定网站上暂时重新启用这些事件。此外,还有一项名为 MutationEventsEnabled企业政策,其运作方式与此类政策类似,适用于企业用户。无论选择哪种选项,您都可以额外获得大约 9 个月的时间来进行迁移(如果需要)。