Signatur
Beschreibung
getRootNode() läuft vom aktuellen Knoten über die Elternkette nach oben und gibt den obersten Knoten zurück. Bei einem Element, das normal im Dokument hängt, ist das das Document. Liegt das Element in einem Shadow DOM, ist es standardmäßig die zugehörige ShadowRoot. Hängt der Knoten nirgends ein (zum Beispiel ein mit document.createElement() erzeugtes Element, das noch nicht eingefügt wurde), ist es der oberste Vorfahre des losgelösten Teilbaums oder der Knoten selbst.
Die Methode ist vor allem für Web Components nützlich. Eine Komponente kann damit herausfinden, ob sie im Shadow DOM einer anderen Komponente liegt, und dann in genau diesem Baum Elemente suchen (root.getElementById(), root.querySelector()), Styles einhängen oder das aktive Element abfragen (root.activeElement). Das funktioniert unabhängig davon, ob die Komponente im Dokument oder in einem Shadow Root steckt.
Mit der Option { composed: true } überspringt die Methode Shadow-Grenzen: Sie geht von jeder ShadowRoot zu deren Host-Element weiter und landet am Ende beim Document, wenn der Knoten eingehängt ist, sonst beim obersten losgelösten Knoten. So lässt sich zuverlässig prüfen, ob ein Knoten im „flachen“ Gesamtbaum des Dokuments hängt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options | Object | { composed: false } | Optionales Konfigurationsobjekt. |
| $options.composed | boolean | false | Bei true werden Shadow-Grenzen überschritten und der Rückgabewert ist die Wurzel des gesamten Baums (meist Document). Bei false endet die Suche an der nächsten ShadowRoot. |
Rückgabewert
Document oder eine ShadowRoot, bei losgelösten Teilbäumen ein beliebiger Node (etwa ein Element oder DocumentFragment) oder der Knoten selbst.Beispiele
Wurzel im normalen Dokument und bei losgelösten Knoten
const p = document.createElement('p');
console.log(p.getRootNode() === p); // noch nicht eingehängt
const wrapper = document.createElement('div');
wrapper.append(p);
console.log(p.getRootNode() === wrapper); // oberster Knoten des Teilbaums
document.body.append(wrapper);
console.log(p.getRootNode() === document);
Shadow Root vs. composed: true
const host = document.createElement('div');
document.body.append(host);
const shadow = host.attachShadow({ mode: 'open' });
const button = document.createElement('button');
shadow.append(button);
console.log(button.getRootNode() === shadow);
console.log(button.getRootNode() instanceof ShadowRoot);
console.log(button.getRootNode({ composed: true }) === document);
Web Component: im eigenen Baum suchen
class FieldLabel extends HTMLElement {
connectedCallback() {
// Funktioniert sowohl im Dokument als auch im Shadow DOM einer anderen Komponente
const root = this.getRootNode();
const target = root.getElementById(this.getAttribute('for'));
this.textContent = target ? `Label für #${target.id}` : 'Ziel nicht gefunden';
}
}
customElements.define('field-label', FieldLabel);
const host = document.createElement('div');
document.body.append(host);
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = '<input id="email"><field-label for="email"></field-label>';
console.log(shadow.querySelector('field-label').textContent);
Prüfen, ob ein Knoten wirklich im Dokument hängt
const isInDocument = (node) =>
node.getRootNode({ composed: true }) === document;
const el = document.createElement('span');
console.log(isInDocument(el));
document.body.append(el);
console.log(isInDocument(el));
// Wichtig · Fallstricke
- Ohne
composed: trueist der Rückgabewert bei Knoten im Shadow DOM eineShadowRootund nichtdocument. Ein Vergleich mitdocumentgeht dann still schief. - Für die reine Frage „Hängt der Knoten im Dokument?“ ist
node.isConnectedkürzer und schneller. Es liefert dasselbe wiegetRootNode({ composed: true }) === document. - Die Methode überschreitet auch geschlossene Shadow Roots (
mode: 'closed'), wenn der Aufruf von innen kommt, und gibt dann die geschlosseneShadowRootzurück. Von außen ist sie nicht erreichbar, weil man keinen Zugriff auf die inneren Knoten hat. - Knoten in einem
<template>gehören zum Inhalts-Fragment. Ihre Wurzel ist deshalb dasDocumentFragmentaustemplate.content, nicht das Dokument. - Der Aufwand wächst mit der Tiefe des Baums, weil die Methode die Elternkette durchläuft. In Hot Paths das Ergebnis zwischenspeichern.
- Nicht unterstützt im Internet Explorer und in Edge-Versionen vor 79 (Legacy). Dort braucht man ein Polyfill, das über
parentNodeundhostläuft.