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