Przenoszenie elementu DOM bez utraty stanu

Funkcje internetowe: moveBefore()

Podczas zmiany elementu nadrzędnego elementów DOM za pomocą tradycyjnych metod, takich jak appendChild() lub insertBefore(), przeglądarka domyślnie usuwa element z DOM, a następnie wstawia go w nowej lokalizacji. Ta operacja „usuń i wstaw” resetuje wiele stanów wewnętrznych, co powoduje ponowne wczytanie elementów <iframe>, ponowne uruchomienie animacji CSS i utratę zaznaczenia pól do wprowadzania danych.

Aby przenieść element z zachowaniem jego stanu, użyj interfejsu API moveBefore(). Ta metoda wykonuje przeniesienie niepodzielne, całkowicie pomijając etapy usuwania i wstawiania.

Przenoszenie elementu ze stanem

Używaj moveBefore() dokładnie tak samo jak insertBefore(). Wymaga 2 argumentów: węzła do przeniesienia i węzła referencyjnego, przed którym ma zostać wstawiony (lub null, aby dołączyć go na końcu nowego węzła nadrzędnego).

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);

Przenoszenie elementów niestandardowych (komponentów sieciowych)

Jeśli przenosisz elementy niestandardowe za pomocą moveBefore(), ich metody cyklu życia connectedCallback i disconnectedCallback nie zostaną wywołane.

Jeśli element niestandardowy musi wykonywać określoną logikę po przeniesieniu, zaimplementuj metodę connectedMoveCallback() w definicji elementu niestandardowego.

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.
  }
}

Strategie zastępcze

moveBefore() to progresywne ulepszanie, dlatego PRZED wywołaniem tej funkcji MUSISZ użyć wykrywania funkcji, a w przypadku starszych przeglądarek wrócić do tradycyjnych operacji insertBefore() lub 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);
}