宣布變異事件的淘汰和移除計畫,並分享如何在 2024 年 7 月移除前遷移程式碼。
Chromium 已正式淘汰突變事件,並計劃從 127 版開始移除支援,該版本將於 2024 年 7 月 23 日推出穩定版。本文將說明我們移除變異事件的原因,並提供在變異事件從瀏覽器移除前,遷移的路徑。
什麼是變異事件?
變異事件是下列事件集合的名稱:
DOMNodeInserted
DOMNodeRemoved
DOMSubtreeModified
DOMCharacterDataModified
DOMNodeInsertedIntoDocument
DOMNodeRemovedFromDocument
- (任何新式瀏覽器都不支援)
DOMAttrModified
- (任何新式瀏覽器都不支援)
DOMAttributeNameChanged
- (任何新式瀏覽器都不支援)
DOMElementNameChanged
這些事件是 DOM 2 級規格的舊版內容,自 2011 年起已淘汰。這些方法已由 MutationObserver 介面取代,自 2013 年起,所有新版瀏覽器都已支援。
變化事件的記錄
變異事件在很久以前聽起來是個好點子,但實際上有幾個致命缺陷:
- 它們太冗長,而且觸發頻率過高。系統會針對每個移除的節點觸發事件。
- 由於事件傳播,且會阻止許多通用 Analytics 執行階段最佳化,因此這些事件會緩慢。
- 這類程式經常會導致當機。這些事件是瀏覽器中許多當機和安全性錯誤的來源,因為事件接聽器可以變更執行中的 DOM 作業下的整個 DOM。
由於這些缺陷,這些事件在 2011 年已淘汰,並在 2012 年建構了替換 API (MutationObserver
)。新版 API 已實作並運作超過 10 年。
為何移除突變事件
不同瀏覽器對突變事件的支援情形不同。部分事件 (例如 DOMNodeInsertedIntoDocument
和 DOMNodeRemovedFromDocument
) 並未在所有瀏覽器中支援。對於其他事件,由於缺乏任何約定的規格,因此特定行為會有所不同。不過,合理的問題可能是:既然這些元素「已完成」,且只會讓使用這些元素的網頁變慢,為何不保留這些元素?答案分為兩部分。
首先,這些事件會拖慢網頁平台的速度。隨著網路的演進,新的 API 也隨之增加,因此必須考量這些舊版 API 的存在。有時,只要需要支援這些事件,就可能無法提出新的 API。舉例來說,長期以來都有人提出要求,希望在 <iframe>
元素在 DOM 中移動時,系統不要重新載入該元素。不過,部分原因是因為變異事件的存在,因此我們認為這項工作難以完成,因此關閉了這項要求。
這些事件會持續影響瀏覽器的速度。即使瀏覽器已進行最佳化,試圖避免未使用突變事件的網頁發生效能懲罰,但仍無法完全避免。但 Mutation Event 事件監聽器仍需要在許多地方進行檢查。由於這些事件可能會以意想不到的方式變更 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 套件形式提供。
- https://github.com/mfreed7/mutation-events-polyfill#readme
- https://www.npmjs.com/package/mutation-events
時程和淘汰前測試資訊
所有使用者* 的 Chrome 127 版將在 2024 年 7 月 23 日推出穩定版,屆時變異事件將從中移除。我們會提早在 Canary、Dev 和 Beta 版中移除這些事件,以便提前發出警告。