Element: attachShadow()-Methode
Baseline
Weitgehend verfügbar
*
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit Januar 2020 browserübergreifend verfügbar.
* Einige Teile dieser Funktion werden möglicherweise unterschiedlich gut unterstützt.
Die attachShadow()-Methode des Element-Interfaces hängt einen Shadow-DOM-Baum an das angegebene Element an und gibt eine Referenz auf dessen ShadowRoot zurück.
Syntax
attachShadow(options)
Parameter
options-
Ein Objekt, das die folgenden Felder enthält:
mode-
Ein String, der den Kapselungsmodus für den Shadow-DOM-Baum angibt. Dies kann einer der folgenden sein:
open-
Elemente innerhalb der Shadow-Root sind von JavaScript über die
shadowRoot-Eigenschaft des Elements zugänglich. closed-
Elemente innerhalb der Shadow-Root können von JavaScript über die
shadowRoot-Eigenschaft nicht zugegriffen werden, welche aufnullgesetzt ist.
clonableOptional-
Ein boolean, der angibt, ob die Shadow-Root clonable ist: Wenn auf
truegesetzt, wird der Shadow-Host, der mitNode.cloneNode()oderDocument.importNode()geklont wurde, die Shadow-Root in die Kopie aufnehmen. Der Standardwert istfalse. customElementRegistryOptional-
Ein
CustomElementRegistry, das als scoped custom element registry der angehängten Shadow-Root verwendet wird. Wennnulloderundefined, verwendet die Shadow-Root das globale Register, auf welches durchWindow.customElementszugegriffen wird. delegatesFocusOptional-
Ein boolean, das, wenn auf
truegesetzt, ein Verhalten spezifiziert, das Probleme von benutzerdefinierten Elementen rund um die Fokussierbarkeit mindert. Wenn ein nicht fokussierbarer Teil des Shadow-DOM angeklickt wird, wird der erste fokussierbare Teil fokussiert, und der Shadow-Host erhält jegliche verfügbare:focus-Stilierung. Der Standardwert istfalse. referenceTargetOptional-
Ein String-Wert, der das effektive Ziel eines jeden Element-Referenzierungsversuchs gegen den Shadow-Host von außerhalb des Host-Elements angibt. Der Wert sollte die ID eines Elements innerhalb des Shadow-DOM sein. Wenn gesetzt, werden Ziel-Referenzen auf das Host-Element von außerhalb des Shadow-DOM dazu führen, dass das referenzierte Ziel-Element das effektive Ziel der Referenz auf das Host-Element wird.
serializableOptional-
Ein boolean, der, wenn auf
truegesetzt, anzeigt, dass die Shadow-Root serialisierbar ist. Wenn gesetzt, kann die Shadow-Root durch Aufrufen der MethodenElement.getHTML()oderShadowRoot.getHTML()mit dem Parameteroptions.serializableShadowRootsauftrueserialisiert werden. Der Standardwert istfalse. slotAssignmentOptional-
Ein String, der den Slot-Zuweisungsmodus für den Shadow-DOM-Baum angibt. Dies kann einer der folgenden sein:
named-
Elemente werden automatisch zu
<slot>-Elementen innerhalb dieser Shadow-Root zugewiesen. Alle obersten Kinder des Hosts mit einemslot-Attribut, welches mit demname-Attribut eines<slot>innerhalb dieser Shadow-Root übereinstimmt, werden diesem Slot zugewiesen. Alle obersten Kinder des Hosts ohneslot-Attribut werden dem ersten<slot>ohnename-Attribut (dem "Standard-Slot") zugewiesen, falls vorhanden. Dies ist der Standardwert. manual-
Elemente werden manuell bestimmten Slot-Elementen mithilfe von
HTMLSlotElement.assign()zugewiesen. Es findet keine automatische Zuweisung statt.
Rückgabewert
Gibt ein ShadowRoot-Objekt zurück.
Ausnahmen
NotSupportedErrorDOMException-
Dieser Fehler kann auftreten, wenn Sie versuchen, eine Shadow-Root an ein Element zu hängen:
- außerhalb des HTML-Namespaces oder das kein Shadow zulassen kann.
- bei dem die statische Eigenschaft
disabledFeaturesdes Element-Definitionsobjekts den Wert"shadow"hat. - das bereits eine Shadow-Root hat, die nicht deklarativ erstellt wurde.
- die eine declarative shadow root hat, aber der angegebene
modenicht mit dem vorhandenen Modus übereinstimmt. - während ein
customElementRegistry-Wert übergeben wird, der nichtnulloder ein lokal begrenztes Register (das Sie mitnew CustomElementRegistry()erstellt haben) ist. Der Fehler würde auftreten, wenn Sie das globale Register übergeben haben.
Beschreibung
Die Element.attachShadow()-Methode fügt das Shadow-DOM-Baum dem angegebenen Element hinzu und gibt eine Referenz auf dessen ShadowRoot zurück.
Dies ist der programmatische Mechanismus zur Erstellung einer ShadowRoot, die der Wurzelknoten eines Shadow DOM an ein Host-Element angehängt ist (es ist auch möglich, eine ShadowRoot deklarativ mit dem shadowrootmode-Attribut des <template>-Elements zu erstellen).
Es wird zur Erstellung von benutzerdefinierten Elementen verwendet.
Elemente, an die Sie einen Shadow anhängen können
Beachten Sie, dass Sie nicht an jeden Elementtyp eine Shadow-Root anhängen können.
Es gibt einige, die aus Sicherheitsgründen kein Shadow-DOM haben können (zum Beispiel <a>).
Die folgende Liste zeigt Elemente, an die Sie eine Shadow-Root anhängen können:
Aufrufen dieser Methode für ein Element, das bereits ein Shadow-Host ist
Die Methode kann für ein Element aufgerufen werden, das bereits eine declarative shadow root hat, vorausgesetzt der spezifizierte mode entspricht dem vorhandenen Modus.
In diesem Fall wird die bereits vorhandene ShadowRoot gelöscht und zurückgegeben.
Dies erlaubt Fälle, in denen beispielsweise serverseitiges Rendering bereits deklarativ eine Shadow-Root erstellt hat und dann clientseitiger Code versucht, die Root erneut anzuhängen.
Andernfalls wirft der Aufruf von attachShadow() für ein Element, das bereits eine Shadow-Root hat, eine Ausnahme.
Offene und geschlossene Shadow-Roots
Eine Shadow-Root kann mit einem Kapselungs-Modus verknüpft werden, der entweder als open oder closed angegeben wird.
Wenn das Argument {mode: "open"} übergeben wird, kann die shadowRoot-Eigenschaft des Host-Elements anschließend verwendet werden, um die angehängte Shadow-Root zu erhalten.
Dies kann verwendet werden, um auf Elemente im Shadow-DOM zuzugreifen:
element.attachShadow({ mode: "open" });
element.shadowRoot; // Returns a ShadowRoot obj
Wenn {mode: "closed"} übergeben wird, wird die shadowRoot-Eigenschaft des Elements auf null gesetzt.
Beachten Sie, dass JavaScript dennoch auf eine geschlossene Shadow-Root zugreifen kann, indem der von der Funktion zurückgegebene Wert gespeichert wird.
element.attachShadow({ mode: "closed" });
element.shadowRoot; // Returns null
Beispiele
>Word-Count-Benutzerelement
Das folgende Beispiel stammt aus unserem word-count-web-component-Beispiel (Siehe es auch live).
Sie können sehen, dass wir attachShadow() in der Mitte des Codes verwenden, um eine Shadow-Root zu erstellen, an die wir die Inhalte unseres benutzerdefinierten Elements anhängen.
// Create a class for the element
class WordCount extends HTMLParagraphElement {
constructor() {
// Always call super first in constructor
super();
// count words in element's parent element
const wcParent = this.parentNode;
function countWords(node) {
const text = node.innerText || node.textContent;
return text
.trim()
.split(/\s+/g)
.filter((a) => a.trim().length > 0).length;
}
const count = `Words: ${countWords(wcParent)}`;
// Create a shadow root
const shadow = this.attachShadow({ mode: "open" });
// Create text node and add word count to it
const text = document.createElement("span");
text.textContent = count;
// Append it to the shadow root
shadow.appendChild(text);
// Update count when element content changes
this.parentNode.addEventListener("input", () => {
text.textContent = `Words: ${countWords(wcParent)}`;
});
}
}
// Define the new element
customElements.define("word-count", WordCount, { extends: "p" });
Deaktivierung des Shadow-DOM
Wenn das Element eine statische Eigenschaft namens disabledFeatures hat, die ein Array mit dem String "shadow" ist, wird der attachShadow()-Aufruf eine Ausnahme werfen.
Zum Beispiel:
class MyCustomElement extends HTMLElement {
// Disable shadow DOM for this element.
static disabledFeatures = ["shadow"];
constructor() {
super();
}
connectedCallback() {
// Create a shadow root.
// This will throw an exception.
const shadow = this.attachShadow({ mode: "open" });
}
}
// Define the new element
customElements.define("my-custom-element", MyCustomElement);
Benannte Slot-Zuweisung
Dieses Beispiel demonstriert die Zuweisung benannter Slots.
Erstellung des Web-Components
Dieser Code erstellt eine Web-Komponente, die drei benannte Slots für den Titel, die Metadaten und den Textkörper eines Artikels hat.
Die ShadowRoot wird im Konstruktor des benutzerdefinierten Elements angehängt.
Wir müssen die Option slotAssignment: "named" nicht explizit setzen, da sie der Standard ist.
class MyArticle extends HTMLElement {
constructor() {
super();
// Attach the shadow root
this.attachShadow({ mode: "open" /* , slotAssignment: "named" */ });
}
connectedCallback() {
this.render();
}
render() {
// Define the internal structure and styles
this.shadowRoot.innerHTML = `
<style>
.header {
background-color: plum;
}
.meta {
background-color: green;
}
.body {
background-color: lightblue;
}
</style>
<h2 class="header">
<slot name="title"></slot>
</h2>
<div class="meta">
<slot name="meta"></slot>
</div>
<div class="body">
<slot></slot>
</div>
`;
}
}
// Register the component
customElements.define("my-article", MyArticle);
Verwendung des Web-Components
Der folgende HTML-Code verwendet das <my-article>-Web-Komponente, die wir gerade erstellt haben.
Die verschachtelten Elemente werden in den Slots der Komponente anhand der Namenszuordnung gerendert.
Die nicht benannten Elemente werden in dem unbenannten Slot der Komponente (dem Hauptteil) gerendert.
<my-article>
<span slot="title">Text for the title slot</span>
<span slot="meta">Text for the meta slot</span>
<p>
Text 1 with no slot attribute. Goes into default (unnamed) slot inside the
"body" div.
</p>
<p>
Text 2 with no slot attribute. Also goes into default (unnamed) slot inside
the "body" div.
</p>
</my-article>
Ergebnisse
Das unten stehende Beispiel sollte den Inhalt der Slots in den entsprechenden Abschnitten anzeigen.
Unbenannte Slot-Zuweisung
Dieses Beispiel demonstriert die manuelle Slot-Zuweisung.
Mit diesem Ansatz muss jedes Element manuell einem bestimmten Slot mit Hilfe von HTMLSlotElement.assign() zugewiesen werden.
Es gibt keine Standardzuweisung, sodass jeder Slot, der nicht zugewiesen ist, leer bleibt.
HTML
Zuerst haben wir eine versteckte Unterstützung-Warnung, die über JavaScript angezeigt wird, wenn der Browser slotAssignment: "manual" nicht unterstützt.
<p id="support-warning" hidden>
⛔ Your browser doesn't support manual slot assignment (named assignment is
used).
</p>
Als nächstes definieren wir unser <my-article>-benutzerdefiniertes Element mit Kind-Elementen für den Titel, die Metadaten und den Inhalt des Textkörpers.
Jedes Kind wird durch id identifiziert; im Gegensatz zur benannten Slot-Zuweisung ist kein slot-Attribut erforderlich.
<my-article>
<span id="text_title">Text for the title slot</span>
<span id="text_meta">Text for the meta slot</span>
<p id="text_body_1">Text 1 for body slot.</p>
<p id="text_body_2">Text 2 for body slot.</p>
</my-article>
JavaScript
Das benutzerdefinierte Element hängt eine Shadow-Root mit slotAssignment: "manual" an.
Der Shadow-DOM enthält unbenannte Slots, die durch id identifiziert werden.
Die assignSlots()-Methode weist die Light-DOM-Elemente manuell den Slots zu.
Beachten Sie, dass mehrere Knoten einem einzelnen Slot zugewiesen werden können — die Reihenfolge, in der sie angegeben werden, steuert die Darstellungsreihenfolge.
class MyArticle extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open", slotAssignment: "manual" });
}
connectedCallback() {
this.render();
this.assignSlots();
}
render() {
this.shadowRoot.innerHTML = `
<style>
.header {
background-color: plum;
}
.meta {
background-color: green;
}
.body {
background-color: lightblue;
}
</style>
<h2 class="header">
<slot id="titleSlot"></slot>
</h2>
<div class="meta">
<slot id="metaSlot"></slot>
</div>
<div class="body">
<slot id="bodySlot"></slot>
</div>
`;
}
assignSlots() {
// 1. Target your slots
const titleSlot = this.shadowRoot.querySelector("#titleSlot");
const metaSlot = this.shadowRoot.querySelector("#metaSlot");
const bodySlot = this.shadowRoot.querySelector("#bodySlot");
// 2. Target your light DOM elements
const titleText = this.querySelector("#text_title");
const metaText = this.querySelector("#text_meta");
const body1Text = this.querySelector("#text_body_1");
const body2Text = this.querySelector("#text_body_2");
// 3. Manually assign them
titleSlot.assign(titleText);
metaSlot.assign(metaText);
bodySlot.assign(body2Text, body1Text);
}
}
customElements.define("my-article", MyArticle);
Dieser Code testet, ob die ShadowRoot.slotAssignment-Eigenschaft definiert ist und zeigt die Warnung an, wenn sie nicht definiert ist.
const isSlotAssignmentSupported = Object.hasOwn(
ShadowRoot.prototype,
"slotAssignment",
);
document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isSlotAssignmentSupported);
Ergebnisse
Das unten stehende Beispiel sollte den Inhalt der Slots in den entsprechenden Abschnitten anzeigen.
Hinweis:
Wenn die manuelle Slot-Zuweisung nicht unterstützt wird, wird eine Warnung angezeigt und der Browser verwendet die named-Zuweisung.
Da jedoch keiner der Light-DOM-Elemente ein slot-Attribut hat, werden sie alle im ersten unbenannten Slot (dem Titel-Slot) eingefügt.
Spezifikationen
| Spezifikation |
|---|
| DOM> # dom-element-attachshadow> |
Browser-Kompatibilität
Siehe auch
ShadowRoot.modeShadowRoot.delegatesFocusShadowRoot.slotAssignment- Deklaratives Anhängen einer Shadow-Root mit dem
shadowrootmode-Attribut des<template>Elements - Deklarativer Shadow DOM auf web.dev (2023)