هنگام تغییر والد عناصر DOM بااستفاده از روشهای سنتی مانند appendChild() یا insertBefore()، مرورگر بهطور ضمنی عنصر را از 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);
}