很高興在此宣布,Chrome 133 版推出全新的 moveBefore()
DOM API,讓您更輕鬆地在 DOM 中移動元素,且不會遺失狀態。請繼續閱讀,瞭解如何在專案中使用這項功能!
在 DOM 突變期間遺失狀態
您是否使用 appendChild()
API 將新元素插入 DOM?許多人都有,但您是否曾經試著呼叫 insertBefore()
或任何其他插入 API,並使用已在 DOM 中的元素?如果是這樣,您可能不知道系統會先從舊父項移除元素,然後重新插入新父項,以便悄悄執行這項操作。這是因為自 1998 年第一版 DOM 標準草案推出以來,Document Object Model 就只有移除和插入原始碼。每當您認為自己在 DOM 中將某些內容從一個位置「移動」到另一個位置時,實際上是在幕後移除和插入。
雖然「移動」其實是「移除並插入」,但這對使用者體驗通常不會有任何影響。舉例來說,當您在 DOM 中「移動」<p>
時,這兩個作業不會造成干擾性的副作用,但如果移動儲存重要狀態的複雜節點 (例如 <iframe>
元素、全螢幕元素、CSS 動畫等),隱含的「移除」作業會重設所有狀態。
這可能會造成意想不到的副作用
您可以透過 DOM 樹狀結構中的移動操作,查看在狀態保留示範網站中重設的狀態類型。以下範例顯示從一個父項容器將元素移至另一個父項容器時,CSS 動畫和 <iframe>
狀態重設的情況。
這項限制可能會導致建構動態使用者體驗的難度提高,甚至無法建構。當應用程式狀態莫名重設時,使用者會感到困惑和挫折,而 JavaScript 架構作者則會因此承受重創,因為他們必須花費無數小時,針對這個問題重新架構前端程式碼、編寫 MorphDOM 等複雜的程式庫,或是處理「他們無法修正的問題」的錯誤回報。
新的 moveBefore()
API
我們著手修正這個問題,方法是在 DOM 中新增新的原始運算。這個元素適當地稱為「move」原始元素,並透過新的 moveBefore()
DOM API 向開發人員公開。
moveBefore()
會採用與 insertBefore()
相同的引數,但在節點已連結至 DOM 時,這個新 API 不會移除及重新插入節點,而是以原子方式移動目標節點至新的父項,且不會重設大部分狀態。這終於讓 JavaScript 開發人員能夠運用可移動的動畫、iframe、全螢幕元素等,打造動態體驗。如要親自試用這項功能,請啟用 chrome://flags/#atomic-move
實驗性標記,並造訪我們的示範網站,或是在 2025 年 2 月 4 日 Chrome 133 版推出後使用該版本。
以下是這個新原始元素可讓 JavaScript 作者達成的行為範例:
- 在使用者瀏覽網站時保留影片的播放狀態 (無論影片是否由
<video>
或<iframe>
元素提供)。 - 在 DOM 中移動使用者輸入欄位時,保留該欄位的焦點。
- 在 DOM 中新增或移除新內容時,讓動畫順利完成。
- 更高精確度的變形演算法,可將現有的 DOM 與新內容調和。
- 保持互動式對話方塊、彈出式視窗和全螢幕元素開啟。
我們正努力將這個 API 引進網頁平台,並與其他瀏覽器整合,我們很高興能盡快將這個 API 交給開發人員,滿足開發人員多年來的請求,並填補網頁平台的重大缺口。
和往常一樣,歡迎透過 Twitter 與我們分享您的想法或在下方留言,並將錯誤提交至 crbug.com/new。