Start · Sprachen · JavaScript · Referenz · DocumentFragment.moveBefore()

DocumentFragment.moveBefore()

Methode

Verschiebt einen Knoten, der schon im <code>DocumentFragment</code> liegt, als direktes Kind vor einen Referenzknoten. Der Knoten wird dabei nicht entfernt und neu eingefügt.

seit JavaScript Chromium 133+ (Chrome, Edge, Opera); in anderen Br Kategorie: webapi

Signatur

DocumentFragment.prototype.moveBefore(movedNode, referenceNode)

Beschreibung

moveBefore() gehört zur „Atomic Move“-API. Mit ihr lässt sich ein Knoten innerhalb eines Baums umsetzen, ohne ihn erst zu entfernen und dann neu einzufügen. Das klassische insertBefore() macht genau das: Es entfernt den Knoten und fügt ihn wieder ein. Dadurch gehen Zustände verloren, etwa der Fokus, laufende CSS-Animationen und Transitions oder der geladene Inhalt eines <iframe>. moveBefore() behält diese Zustände bei.

Beim DocumentFragment gilt eine wichtige Einschränkung: Der zu verschiebende Knoten muss bereits im selben Fragment liegen. Die Methode prüft, ob Knoten und Fragment dieselbe Wurzel haben (die „shadow-including root“). Ein Fragment ist immer seine eigene Wurzel. Deshalb lassen sich nur Knoten umsetzen, die schon darin stecken, entweder als direkte Kinder oder tiefer verschachtelt. Knoten aus dem Dokument oder aus einem anderen Fragment kann man so nicht holen.

Man nutzt die Methode, um den Inhalt eines Fragments umzusortieren, bevor er ins Dokument kommt, oder um einen tiefer verschachtelten Knoten auf die oberste Ebene zu holen. Für Fragmente ist der Nutzen kleiner als im Live-DOM, weil Fragmente nicht mit dem Dokument verbunden sind. Die Methode ist aber Teil der gemeinsamen Schnittstelle, die es auch bei Element und Document gibt.

Parameter

Name Typ Default Beschreibung
$movedNode Pflicht Element | CharacterData Der Knoten, der verschoben wird. Erlaubt sind nur Elemente und Zeichendaten-Knoten (Text, Comment). Der Knoten muss schon im selben Fragment liegen.
$referenceNode Pflicht Node | null Das direkte Kind des Fragments, vor dem movedNode eingefügt wird. Bei null landet der Knoten als letztes Kind am Ende. Das Argument ist Pflicht und darf nicht weggelassen werden.

Rückgabewert

Typ
undefined
Beschreibung
Die Methode gibt nichts zurück. Sie ändert das Fragment direkt.

Beispiele

Einträge im Fragment umsortieren, bevor sie ins Dokument kommen

const fragment = document.createDocumentFragment();

['Banane', 'Apfel', 'Kirsche'].forEach((name) => {
  const li = document.createElement('li');
  li.textContent = name;
  fragment.append(li);
});

// "Apfel" (2. Kind) vor "Banane" (1. Kind) setzen
const [banane, apfel] = fragment.children;
fragment.moveBefore(apfel, banane);

console.log([...fragment.children].map((li) => li.textContent));
document.querySelector('ul').append(fragment);
["Apfel", "Banane", "Kirsche"]

Verschachtelten Knoten mit null ans Ende holen

const fragment = document.createDocumentFragment();
const wrapper = document.createElement('div');
const hinweis = document.createElement('p');
hinweis.textContent = 'Hinweis';
wrapper.append(hinweis);
fragment.append(wrapper, document.createElement('footer'));

// <p> liegt im selben Fragment (im div) und wird direktes Kind am Ende
fragment.moveBefore(hinweis, null);

console.log([...fragment.childNodes].map((n) => n.nodeName));
["DIV", "FOOTER", "P"]

Funktionsprüfung mit Rückfall auf insertBefore()

const moveInto = (parent, node, ref) => {
  if ('moveBefore' in parent) {
    try {
      parent.moveBefore(node, ref);
      return;
    } catch (err) {
      // z. B. HierarchyRequestError: Knoten liegt nicht im Fragment
      if (err.name !== 'HierarchyRequestError') throw err;
    }
  }
  parent.insertBefore(node, ref);
};

const fragment = document.createDocumentFragment();
const a = document.createElement('span');
const b = document.createElement('em');
fragment.append(a, b);
moveInto(fragment, b, a);
console.log(fragment.firstChild.nodeName);
EM

Fehlerfall: Knoten stammt nicht aus dem Fragment

const fragment = document.createDocumentFragment();
const fremd = document.createElement('div'); // nicht im Fragment

try {
  fragment.moveBefore(fremd, null);
} catch (err) {
  console.log(err.name);
}
HierarchyRequestError

// Wichtig · Fallstricke

Fehler, die auftreten können:

  • HierarchyRequestError: movedNode liegt nicht im selben Fragment (andere Wurzel). Dasselbe gilt, wenn er kein Element und kein CharacterData-Knoten ist oder wenn er ein Vorfahre des Ziels wäre.
  • NotFoundError: referenceNode ist weder null noch ein direktes Kind des Fragments.
  • TypeError: Das zweite Argument fehlt. Anders als bei manchen DOM-Methoden muss referenceNode ausdrücklich übergeben werden, notfalls als null.

Wann man insertBefore() nimmt: Um Knoten von außen in ein Fragment zu holen, bleiben insertBefore(), append() oder prepend() der richtige Weg. moveBefore() taugt nur für Verschiebungen innerhalb desselben Baums.

MutationObserver: Ein Beobachter erhält auch bei einem Verschieben Mutations-Einträge für das Entfernen und das Hinzufügen. Custom Elements mit einem connectedMoveCallback() bekommen diesen Callback statt disconnectedCallback und connectedCallback.

Kompatibilität: Die Methode ist noch relativ neu. Sie gibt es in Chromium-Browsern ab Version 133, in anderen Engines teils noch nicht. Vor dem Einsatz sollte man mit 'moveBefore' in fragment prüfen, ob sie verfügbar ist, und einen Rückfall auf insertBefore() vorsehen.