網頁功能:
moveBefore()
使用 appendChild() 或 insertBefore() 等傳統方法重新設定 DOM 元素的父項時,瀏覽器會隱含地從 DOM 中移除元素,然後將元素插入新位置。這項「移除並插入」作業會重設許多內部狀態,導致 <iframe> 元素重新載入、CSS 動畫重新啟動,以及輸入欄位失去焦點。
如要移動元素並保留其狀態,請使用 moveBefore() API。這個方法會執行原子移動,完全略過移除和插入步驟。
移動具有狀態的元素
moveBefore() 的使用方式與 insertBefore() 完全相同。這個方法需要兩個引數:要移動的節點,以及要插入之前的參照節點 (或 null,附加到新父項的結尾)。
const newParent = document.getElementById('new-parent');
const elementWithState = document.getElementById('iframe-or-focused-input');
// MANDATORY: Use moveBefore to preserve state.
// Passing null as the second argument appends the element to the end of newParent.
newParent.moveBefore(elementWithState, null);
移動自訂元素 (網頁元件)
如果您使用 moveBefore() 移動自訂元素,系統「不會」觸發其 connectedCallback 和 disconnectedCallback 生命週期方法。
如果自訂元素在移動時需要執行特定邏輯,請在自訂元素定義中實作 connectedMoveCallback() 方法。
class MyCustomElement extends HTMLElement {
connectedCallback() {
// Runs on initial insertion.
}
connectedMoveCallback() {
// Runs when the element is moved via moveBefore().
// Use this to update state that depends on the new DOM location.
}
}
備用策略
由於 moveBefore() 是漸進增強功能,因此您必須先使用功能偵測,再呼叫該功能,並針對舊版瀏覽器改用傳統的 insertBefore() 或 appendChild() 作業。
const targetParent = document.getElementById('target-container');
const nodeToMove = document.getElementById('moving-element');
// Check if moveBefore is supported on the Element prototype
if ('moveBefore' in Element.prototype) {
targetParent.moveBefore(nodeToMove, null);
} else {
// Fallback: traditional move.
// Note: This WILL reset <iframe>, animation, and focus state in unsupported browsers.
targetParent.insertBefore(nodeToMove, null);
}