W3docs

Web Components

JavaScript Web Components von Grund auf: Custom Elements, Shadow DOM, HTML-Templates, Slots und Lifecycle-Callbacks mit ausführbaren Beispielen.

Web Components ermöglichen es Ihnen, eigene wiederverwendbare, gekapselte HTML-Elemente zu erstellen — benutzerdefinierte Tags wie <user-card> oder <star-rating>, die ihre eigene Markup-, Stil- und Verhaltenslogik mitbringen. Da sie auf nativen Browser-APIs basieren, funktionieren sie in jedem Framework (oder ganz ohne Framework) und halten ihre internen Details vom Rest der Seite isoliert. Dieser Leitfaden behandelt die drei Bausteine von Web Components, führt Sie durch die Erstellung einer solchen von Grund auf und schließt mit Lifecycle-Hooks und Best Practices ab.

Wann sollte ich Web Components verwenden?

Greifen Sie auf Web Components zurück, wenn Sie ein in sich geschlossenes UI-Widget benötigen, das:

  • Überall funktioniert — dasselbe <my-widget> lässt sich in eine React-, Vue-, plain-HTML- oder serverseitig gerenderte Seite ohne Build-Schritt einfügen.
  • Isoliert bleibt — seine Stile können dank des Shadow DOM weder nach außen noch von außen nach innen gelangen.
  • Als einzelne Datei ausgeliefert wird — Markup, Stil und Logik befinden sich zusammen, sodass die Komponente einfach zu verteilen und wiederzuverwenden ist.

Design-Systeme, einbettbare Widgets und gemeinsame Komponentenbibliotheken sind die häufigsten Anwendungsfälle.

Einführung in Web Components

Web Components sind eine Reihe von Webplattform-APIs, mit denen Sie neue benutzerdefinierte, wiederverwendbare und gekapselte HTML-Tags erstellen können. Drei Technologien arbeiten zusammen:

  • Custom Elements — definieren neue HTML-Tags und deren Verhalten.
  • Shadow DOM — kapselt das Markup und die Stile einer Komponente, sodass sie auf das Element beschränkt sind.
  • HTML Templates — deklarieren wiederverwendbare Blöcke aus inaktivem Markup, die Sie zur Laufzeit instanziieren.

Custom Elements

Custom Elements definieren neue HTML-Tags und deren Verhalten. Sie bauen auf JavaScript-Klassen auf: Ein Custom Element ist eine Klasse, die HTMLElement erweitert. Nach der Registrierung kann der Tag wie jedes Standard-HTML-Element verwendet werden.

<div>
  <script>
    class MyElement extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = '<p>Hello, World!</p>';
      }
    }
    customElements.define('my-element', MyElement);
  </script>
  <my-element></my-element>
</div>

Dieses Code-Snippet zeigt, wie ein benutzerdefiniertes HTML-Element namens my-element erstellt wird. Die Klasse MyElement erweitert HTMLElement, hängt einen Shadow DOM an, um den Inhalt zu kapseln, und fügt einen einfachen Absatz mit dem Text "Hello, World!" ein.

Shadow DOM

Shadow DOM bietet Kapselung für Ihre Custom Elements. Es ermöglicht Ihnen, einen separaten, verborgenen DOM-Baum (den Shadow Tree) an ein Element anzuhängen und dessen Stile und Markup auf das Element selbst zu beschränken. Einen tieferen Einblick finden Sie im eigenen Kapitel über den JavaScript Shadow DOM.

<div>
  <script>
    class ShadowElement extends HTMLElement {
      constructor() {
        super();
        let shadow = this.attachShadow({ mode: 'open' });
        shadow.innerHTML = `
          <style>
            p { color: blue; }
          </style>
          <p>Shadow DOM content</p>
        `;
      }
    }
    customElements.define('shadow-element', ShadowElement);
  </script>
  <shadow-element></shadow-element>
</div>

In diesem Beispiel erweitert die Klasse ShadowElement den HTMLElement und hängt einen Shadow Root an das Element an. Der Parameter mode: 'open' gibt an, dass der Shadow DOM über JavaScript zugänglich ist. Wenn mode auf 'open' gesetzt ist, kann auf den Shadow Root über die Eigenschaft element.shadowRoot zugegriffen werden. Wenn mode auf 'closed' gesetzt ist, ist der Shadow Root von außen nicht zugänglich, was die Kapselung verbessert und externe Skripte daran hindert, den Shadow DOM direkt zu manipulieren.

Innerhalb des Shadow DOM definieren wir einige Stile und HTML-Inhalte. Die Stile (in diesem Fall ein Absatz mit blauem Text) sind auf den Shadow DOM beschränkt und beeinflussen keine anderen Elemente auf der Seite. Diese Kapselung ist vorteilhaft für die Erstellung wiederverwendbarer Komponenten mit konsistenter Darstellung und Verhalten, unabhängig vom Kontext, in dem sie verwendet werden.

Warnung

Verwenden Sie lokale Stile innerhalb des Shadow DOM, um Stil-Lecks zu verhindern und sicherzustellen, dass Komponentenstile gekapselt bleiben.

Mehr zur Beschränkung von CSS auf einen Shadow Tree — einschließlich :host und CSS Custom Properties, die die Grenze überschreiten können — finden Sie unter Shadow DOM Styling.

HTML Templates

HTML-Templates ermöglichen es Ihnen, wiederverwendbare HTML-Blöcke zu definieren, die inaktiv sind — sie werden geparst, aber nicht gerendert, und ihre Skripte werden nicht ausgeführt — bis Sie sie zur Laufzeit klonen und einfügen. Das <template>-Element ist der standardmäßige Weg, dies zu tun.

<div>
  <template id="my-template">
    <style>
      p { color: red; }
    </style>
    <p>This is a template content</p>
  </template>
  <script>
    const template = document.getElementById('my-template').content;
    document.body.appendChild(template.cloneNode(true));
  </script>
</div>

Dieses Beispiel zeigt, wie HTML-Templates verwendet werden. Der <template>-Tag enthält HTML und Stile, die nicht sofort gerendert werden. Das Skript klont den Inhalt des Templates und hängt ihn an den Dokumentkörper an, wodurch er sichtbar wird.

Ihre erste Web Component erstellen

Lassen Sie uns den Prozess der Erstellung einer voll funktionsfähigen Web Component durchgehen, die in verschiedenen Projekten verwendet werden kann.

Schritt 1: Die Komponente definieren

Erstellen Sie eine neue Klasse, die HTMLElement erweitert.

<div>
  <script>
    class MyComponent extends HTMLElement {
      constructor() {
        super();
        const shadow = this.attachShadow({ mode: 'open' });
        shadow.innerHTML = 'Hello, World!';
      }
    }
    customElements.define('my-component', MyComponent);
  </script>
  <my-component></my-component>
</div>

Dieses Snippet legt das Fundament für eine Web Component namens my-component. Es definiert eine Klasse, die HTMLElement erweitert und einen Shadow DOM anhängt, um ihn für weitere Anpassungen vorzubereiten.

Schritt 2: Stile und Templates hinzufügen

Verwenden Sie den Shadow DOM, um Stile und Templates zu kapseln.

<div>
  <script>
    class MyStyledComponent extends HTMLElement {
      constructor() {
        super();
        let shadow = this.attachShadow({ mode: 'open' });
        shadow.innerHTML = `
          <style>
            p { font-size: 20px; color: green; }
          </style>
          <p>This is my styled component!</p>
        `;
      }
    }
    customElements.define('my-styled-component', MyStyledComponent);
  </script>
  <my-styled-component></my-styled-component>
</div>

Dieses Snippet erweitert my-styled-component durch das Hinzufügen gekapselter Stile innerhalb des Shadow DOM. Der Absatz innerhalb der Komponente wird mit grüner Farbe und vergrößerter Schriftgröße gestaltet.

Schritt 3: Interaktivität hinzufügen

Fügen Sie JavaScript hinzu, um Ihre Komponente interaktiv zu machen.

<div>
  <script>
    class InteractiveComponent extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
          <style>
            p { font-size: 20px; }
          </style>
          <p>This is interactive!</p>
          <button>Click me</button>
        `;
        this.shadowRoot.querySelector('button').addEventListener('click', () => {
          this.shadowRoot.querySelector('p').textContent = 'You clicked!';
        });
      }
    }
    customElements.define('interactive-component', InteractiveComponent);
  </script>
  <interactive-component></interactive-component>
</div>

Dieses Beispiel zeigt, wie eine Web Component interaktiv gemacht wird. Die InteractiveComponent enthält einen Button, der beim Klicken den Textinhalt eines Absatzes innerhalb der Komponente ändert.

Fortgeschrittene Web-Component-Techniken

Lifecycle-Callbacks

Custom Elements verfügen über Lifecycle-Callbacks, mit denen Sie Code in bestimmten Phasen des Lebenszyklus eines Elements ausführen können.

<div>
  <script>
    class LifecycleComponent extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
      }
      connectedCallback() {
        this.shadowRoot.innerHTML = '<p>Element added to page.</p>';
      }
      disconnectedCallback() {
        console.log('Element removed from page.');
      }
    }
    customElements.define('lifecycle-component', LifecycleComponent);
  </script>
  <lifecycle-component></lifecycle-component>
</div>

Dieses Snippet demonstriert die Verwendung von Lifecycle-Callbacks in Web Components. Die LifecycleComponent aktualisiert ihren Inhalt, wenn sie zur Seite hinzugefügt wird, und gibt eine Meldung aus, wenn sie entfernt wird.

Umgang mit Attributänderungen

Reagieren Sie auf Änderungen an den Attributen eines Elements, indem Sie das array observedAttributes definieren und die Methode attributeChangedCallback implementieren.

<div>
  <script>
    class AttributeComponent extends HTMLElement {
      static get observedAttributes() {
        return ['data-text'];
      }
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = '<p></p>';
      }
      attributeChangedCallback(name, oldValue, newValue) {
        if (name === 'data-text') {
          this.shadowRoot.querySelector('p').textContent = newValue;
        }
      }
    }
    customElements.define('attribute-component', AttributeComponent);
  </script>
  <attribute-component data-text="Initial text"></attribute-component>
  <script>
    const element = document.querySelector('attribute-component');
    setTimeout(() => {
      element.setAttribute('data-text', 'Updated text');
    }, 2000);
  </script>
</div>

Dieses Beispiel zeigt, wie Attributänderungen in einer Web Component behandelt werden. Die AttributeComponent aktualisiert ihren internen Inhalt basierend auf Änderungen am Attribut data-text. Beachten Sie, dass attributeChangedCallback nur für Attribute ausgelöst wird, die in observedAttributes aufgeführt sind — ohne diese Liste werden Attributänderungen ignoriert.

Die vier Lifecycle-Callbacks für Custom Elements sind:

CallbackWann er ausgeführt wird
constructor()Wenn das Element erstellt oder aktualisiert wird. Richten Sie hier den Anfangszustand ein, vermeiden Sie aber das Berühren von Attributen oder untergeordnetem DOM.
connectedCallback()Jedes Mal, wenn das Element in das Dokument eingefügt wird. Bester Ort zum Rendern und Hinzufügen von Ereignis-Listenern.
disconnectedCallback()Jedes Mal, wenn das Element aus dem Dokument entfernt wird. Bereinigen Sie hier Listener und Timer.
attributeChangedCallback(name, oldVal, newVal)Wenn sich ein beobachtetes Attribut ändert. Erfordert einen statischen observedAttributes-Getter.

Inhalte mit Slots verteilen

Ein <slot> ermöglicht es einer Komponente, das Markup zu rendern, das ein Benutzer zwischen ihren Tags platziert, sodass Konsumenten eigene Inhalte einbringen können. Dies ist die Grundlage der Komposition mit Web Components — siehe Shadow DOM, Slots und Komposition für das vollständige Bild.

<div>
  <script>
    class CardBox extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.innerHTML = `
          <style>
            .box { border: 1px solid #ccc; padding: 8px; }
          </style>
          <div class="box"><slot>Default content</slot></div>
        `;
      }
    }
    customElements.define('card-box', CardBox);
  </script>
  <card-box>Passed-in content</card-box>
  <card-box></card-box>
</div>

Die erste <card-box> rendert "Passed-in content" innerhalb des gestalteten Rahmens; die zweite greift auf den Standard-Slot-Inhalt "Default content" zurück.

Best Practices für Web Components

Shadow DOM sinnvoll einsetzen

Kapseln Sie Stile und Skripte innerhalb des Shadow DOM, um Konflikte mit anderen Elementen auf der Seite zu vermeiden.

Namenskonventionen befolgen

Custom Elements müssen in ihrem Namen einen Bindestrich enthalten (zum Beispiel my-card, nicht mycard), um Konflikte mit aktuellen und zukünftigen Standard-HTML-Elementen zu vermeiden. Die Registrierung eines Namens ohne Bindestrich führt zu einem Fehler.

Komponenten modular halten

Erstellen Sie kleine, wiederverwendbare Komponenten, um Ihre Codebasis wartbar und skalierbar zu halten.

Globale Stile vermeiden

Verwenden Sie lokale Stile innerhalb des Shadow DOM, um Stil-Lecks zu verhindern und sicherzustellen, dass Komponentenstile gekapselt bleiben.

Dokumentation und Tests

Dokumentieren Sie Ihre Komponenten gut und schreiben Sie Tests, um sicherzustellen, dass sie in verschiedenen Browsern und Anwendungsfällen wie erwartet funktionieren.

Fazit

Web Components sind eine vielseitige und leistungsstarke Funktion der modernen Webentwicklung, die die Erstellung wiederverwendbarer, gekapselter Custom Elements ermöglicht. Durch das Verstehen und Einsetzen von Custom Elements, Shadow DOM und HTML-Templates können Sie modulare, wartbare und skalierbare Webanwendungen erstellen. Dieser Leitfaden hat Ihnen das Wissen und die Beispiele vermittelt, die Sie für den Einstieg in Web Components benötigen, damit Sie diese effektiv in Ihren Projekten einsetzen können.

Um tiefer einzutauchen, erkunden Sie den JavaScript Shadow DOM, wie Shadow DOM und Events zusammenwirken, und das <template>-Element im Detail.

Übungen

Übung
Welche der folgenden Aussagen über Web Components ist korrekt?
Welche der folgenden Aussagen über Web Components ist korrekt?
Was this page helpful?