Start · Sprachen · JavaScript · Referenz · Document.importNode()

Document.importNode()

Methode

Erstellt eine Kopie eines Knotens oder <code>DocumentFragment</code> aus einem anderen Dokument, die anschließend in das aktuelle Dokument eingefügt werden kann.

seit JavaScript DOM Level 2 – Baseline: alle Browser Kategorie: webapi

Signatur

Document.prototype.importNode(externalNode, deep)

Beschreibung

document.importNode() erzeugt eine Kopie eines Knotens, der zu einem anderen Dokument gehört, etwa zu einem <template>-Inhalt, einem <iframe> oder einem mit DOMParser erzeugten Dokument. Die Kopie gehört danach zum aufrufenden Dokument (ownerDocument zeigt auf dieses). Sie hat aber noch keinen Elternknoten und ist daher noch nicht im DOM-Baum sichtbar. Einfügen musst du sie selbst, z. B. mit appendChild() oder append().

Der Originalknoten bleibt im Quelldokument unverändert. Das ist der wichtigste Unterschied zu document.adoptNode(): Diese Methode verschiebt den Knoten und entfernt ihn dabei aus dem Quelldokument.

Typische Einsatzfälle sind das mehrfache Klonen von Vorlagen (template.content), das Übernehmen von Inhalten aus einem per fetch() geladenen und geparsten HTML-Dokument oder das Kopieren von Elementen zwischen Fenstern bzw. Frames. Mit dem Parameter deep legst du fest, ob nur der Knoten selbst oder auch sein gesamter Unterbaum kopiert wird.

Parameter

Name Typ Default Beschreibung
$externalNode Pflicht Node | DocumentFragment Der Knoten aus einem anderen Dokument, der kopiert werden soll. Ein Document oder ShadowRoot kann nicht importiert werden.
$deep boolean false Bei true wird der komplette Unterbaum mitkopiert, also alle Kindknoten und Textinhalte. Bei false wird nur der Knoten selbst mit seinen Attributen kopiert.

Rückgabewert

Typ
Node
Beschreibung
Die Kopie von externalNode. Sie gehört zum aufrufenden Dokument, hat aber noch keinen Elternknoten (parentNode === null).

Beispiele

Template-Inhalt mehrfach klonen

// HTML: <template id="row"><li class="item"><span></span></li></template><ul id="list"></ul>
const template = document.getElementById('row');
const list = document.getElementById('list');

const fruits = ['Apfel', 'Birne', 'Kirsche'];
for (const fruit of fruits) {
  // template.content gehört zu einem eigenen Dokument, daher wird importiert
  const clone = document.importNode(template.content, true);
  clone.querySelector('span').textContent = fruit;
  list.appendChild(clone);
}

console.log(list.children.length);
3

Inhalt aus einem geparsten HTML-Dokument übernehmen

const loadSnippet = async (url) => {
  const html = await (await fetch(url)).text();
  const parsed = new DOMParser().parseFromString(html, 'text/html');
  const article = parsed.querySelector('article');

  const imported = document.importNode(article, true);
  console.log(imported.ownerDocument === document); // true
  document.querySelector('main').append(imported);
};

loadSnippet('/snippets/news.html');
true

Flache und tiefe Kopie im Vergleich

const doc = new DOMParser().parseFromString(
  '<div id="box" class="card"><p>Hallo</p></div>',
  'text/html'
);
const source = doc.getElementById('box');

const shallow = document.importNode(source, false);
const deep = document.importNode(source, true);

console.log(shallow.outerHTML);
console.log(deep.outerHTML);
console.log(source.ownerDocument === doc); // Original bleibt im Quelldokument
<div id="box" class="card"></div> <div id="box" class="card"><p>Hallo</p></div> true

Element aus einem gleichherkünftigen iframe kopieren

const frame = document.querySelector('iframe');
frame.addEventListener('load', () => {
  const header = frame.contentDocument.querySelector('header');
  const copy = document.importNode(header, true);
  document.body.prepend(copy);
});

// Wichtig · Fallstricke

  • Nicht eingefügt: Der zurückgegebene Knoten hängt noch nicht im DOM. Ohne appendChild(), append() o. Ä. ist er nicht sichtbar.
  • Standardwert von deep: Heute ist das false. Ältere Browser verlangten den Parameter zwingend. Gib ihn daher immer ausdrücklich an und setze ihn bei Vorlagen fast immer auf true.
  • Keine Ereignis-Listener: Mit addEventListener() registrierte Listener werden nicht mitkopiert. Inline-Attribute wie onclick dagegen schon, weil sie Attribute sind.
  • Doppelte IDs: Kopien behalten ihre id-Attribute. Bei mehrfachem Import können so doppelte IDs entstehen.
  • Nicht importierbar: Document- und ShadowRoot-Knoten lösen eine NotSupportedError-DOMException aus.
  • Skripte: <script>-Elemente aus einem mit DOMParser erzeugten Dokument gelten als bereits verarbeitet und werden nach dem Import in der Regel nicht ausgeführt.
  • Sicherheit: Übernimmst du HTML aus fremden Quellen, können gefährliche Attribute wie onerror oder javascript:-URLs mitkommen und nach dem Einfügen aktiv werden (XSS). Bereinige nicht vertrauenswürdige Inhalte vorher, etwa mit DOMPurify. Bei iframes gilt die Same-Origin-Policy: Auf das contentDocument fremder Herkunft kannst du nicht zugreifen.
  • Alternative: Bei template.content funktioniert meist auch template.content.cloneNode(true). Beim Einfügen wird der Knoten dann automatisch übernommen. importNode() gibt den richtigen Besitzer aber sofort vor, was z. B. für Custom Elements, die direkt aktualisiert werden, relevant ist.
  • Die Methode wird von allen Browsern unterstützt, einschließlich sehr alter Versionen.