انتقال عنصر DOM بدون ازدست دادن وضعیت

ویژگی‌های وب: moveBefore()

هنگام تغییر والد عناصر 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);
}