Signatur
Beschreibung
initialize() gehört zu den Scoped Custom Element Registries. Mit ihnen kann man eigene, lokale Register per new CustomElementRegistry() anlegen, statt alle Custom Elements global in window.customElements zu registrieren. So können zwei Komponenten-Bibliotheken denselben Tag-Namen (z. B. <my-button>) nutzen, ohne sich in die Quere zu kommen.
Ein Knoten kann ein Register haben oder den Wert null (noch keins zugewiesen). Das passiert z. B. bei deklarativem Shadow DOM mit dem Attribut shadowrootcustomelementregistry: Der Parser erzeugt den Shadow Root absichtlich ohne Register, weil das passende Register erst später per Skript entsteht. Die Elemente darin bleiben so lange unaufgelöst (nicht aktualisiert).
Genau hier kommt initialize(root) ins Spiel: Die Methode durchläuft root samt allen Nachfahren. Jedem Knoten, dessen Register null ist, weist sie dieses Register zu, und für jedes Element wird ein Upgrade versucht. Ist ein Tag-Name im Register definiert, wird das Element also sofort zur fertigen Komponente. Knoten, die schon ein Register haben, bleiben unverändert.
Typische Einsätze: deklarativ vorgerenderten Shadow DOM (SSR) nachträglich an ein lokales Register binden, und Teilbäume ohne Register „reparieren“, etwa Inhalte aus document.implementation.createHTMLDocument() oder aus einem Shadow Root ohne Register.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $root Pflicht | Document | ShadowRoot | Element | Wurzel des Teilbaums, der mit dem Register verknüpft werden soll. Die Methode verarbeitet root selbst und alle Nachfahren (inclusive descendants). |
Rückgabewert
shadowRoot.customElementRegistry oder element.customElementRegistry.Beispiele
Deklarativen Shadow DOM an ein lokales Register binden
// HTML (serverseitig gerendert):
// <user-card id="card">
// <template shadowrootmode="open" shadowrootcustomelementregistry>
// <fancy-avatar src="/a.png"></fancy-avatar>
// </template>
// </user-card>
const host = document.getElementById('card');
const shadow = host.shadowRoot;
console.log(shadow.customElementRegistry); // null – noch kein Register
const registry = new CustomElementRegistry();
registry.define('fancy-avatar', class extends HTMLElement {
connectedCallback() {
this.textContent = `Avatar: ${this.getAttribute('src')}`;
}
});
// Teilbaum verknüpfen und Elemente aktualisieren
registry.initialize(shadow);
console.log(shadow.customElementRegistry === registry);
console.log(shadow.querySelector('fancy-avatar').textContent);
Funktionserkennung mit Fallback auf das globale Register
const supportsScoped =
typeof CustomElementRegistry === 'function' &&
'initialize' in CustomElementRegistry.prototype;
class PriceTag extends HTMLElement {
connectedCallback() {
this.textContent = `${Number(this.dataset.value).toFixed(2)} €`;
}
}
const setupComponent = (shadowRoot) => {
if (supportsScoped && shadowRoot.customElementRegistry === null) {
const registry = new CustomElementRegistry();
registry.define('price-tag', PriceTag);
registry.initialize(shadowRoot);
} else if (!customElements.get('price-tag')) {
// Fallback: global registrieren
customElements.define('price-tag', PriceTag);
}
};
document.querySelectorAll('[data-shop-widget]').forEach((el) => {
if (el.shadowRoot) setupComponent(el.shadowRoot);
});
console.log('Scoped Registries unterstützt:', supportsScoped);
Bereits zugewiesene Knoten bleiben unverändert
const registryA = new CustomElementRegistry();
const registryB = new CustomElementRegistry();
const host = document.createElement('div');
const shadow = host.attachShadow({ mode: 'open', customElementRegistry: registryA });
// Zweiter Aufruf mit anderem Register überschreibt nichts,
// weil der Shadow Root schon registryA besitzt
registryB.initialize(shadow);
console.log(shadow.customElementRegistry === registryA);
// Wichtig · Fallstricke
- Kompatibilität: Scoped Custom Element Registries sind neu (Safari 26+, Chromium in Umsetzung, Firefox noch offen). Prüfe die Unterstützung vorher, z. B. mit
'initialize' in CustomElementRegistry.prototype, oder nutze einen Polyfill (@webcomponents/scoped-custom-element-registry). - Nur Knoten mit Register
nullwerden umgestellt. Ein bereits zugewiesenes Register lässt sich mitinitialize()nicht austauschen. - Globales Register: Wendet man
window.customElements.initialize()auf einDocumentan, das schon ein Register hat, kann eineNotSupportedError-DOMExceptionausgelöst werden. Die Methode ist hauptsächlich für lokale Register gedacht. - Reihenfolge: Elemente werden beim Aufruf nur aktualisiert, wenn ihre Tag-Namen dann schon definiert sind. Später per
define()ergänzte Namen werden aber ebenfalls aktualisiert, weil der Teilbaum jetzt mit dem Register verknüpft ist. - Leistung: Die Methode durchläuft den gesamten Teilbaum. Bei sehr großen Bäumen besser gezielt einen Shadow Root übergeben statt des ganzen Dokuments.
- Die API wird noch standardisiert. Details (z. B. welche Fehler in welchen Fällen ausgelöst werden) können sich ändern.