Web-Technologien 6 Min. Lesezeit

Ein Leitfaden zur Entwicklung skalierbarer Web Components mit Shadow DOM, Custom Elements und Slots

PROFSCODE Ekibi 10 Jul 2026
Paylaş:
Modulare und Wiederverwendbare UI-Entwicklung mit Web Components

In modernen Webanwendungen ist die Verwaltung und Wiederverwendung von UI-Komponenten eine ständige Herausforderung für Entwickler. Während JavaScript-Frameworks Lösungen bieten, ist das Teilen von Komponenten über verschiedene Frameworks oder völlig unabhängig oft schwierig. Hier kommen Web Components ins Spiel. Diese Sammlung von browsernativen Standards ermöglicht es uns, wirklich modulare, gekapselte und framework-unabhängige UI-Komponenten zu erstellen.

Custom Elements: Erstellen Sie Ihre eigenen HTML-Tags

Custom Elements, die das Fundament von Web Components bilden, ermöglichen es Ihnen, Ihre eigenen HTML-Tags zu definieren. Dadurch können Sie projektspezifische, aussagekräftige Tags (z.B. <my-card>) anstelle vorhandener Tags wie <button> oder <div> erstellen. Um ein Custom Element zu erstellen, erweitern Sie die Klasse <code>HTMLElement</code> und registrieren es mit der Methode <code>customElements.define()</code>.


class MyCard extends HTMLElement {
  constructor() {
    super(); // Always call super() first in constructor
    this.innerHTML = `
      <style>
        .card {
          border: 1px solid #ccc;
          padding: 16px;
          border-radius: 8px;
          box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
        }
        h3 {
          color: #333;
        }
      </style>
      <div class="card">
        <h3>Titel</h3>
        <p>Dies ist eine Kartenkomponente.</p>
      </div>
    `;
  }
}

customElements.define('my-card', MyCard);

Nachdem Sie diesen Code in Ihre HTML-Datei eingefügt haben, können Sie Ihre Komponente auf Ihrer Seite mit dem Tag <code><my-card></my-card></code> verwenden.

Shadow DOM: Kapselung mit Komponentenisolation

Custom Elements sind der erste Schritt zur Erstellung einer Komponente. Um jedoch Stil- und Verhaltenskonflikte zu vermeiden, benötigen wir Kapselung. Hier kommt Shadow DOM ins Spiel. Shadow DOM erstellt einen versteckten DOM-Baum, der die interne Struktur und die Stile Ihrer Komponente vom Hauptdokument isoliert. So dringen CSS-Regeln innerhalb Ihrer Komponente nicht nach außen und externe CSS-Regeln wirken sich nicht auf das Innere Ihrer Komponente aus.


class MyShadowCard extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' }); // Attach a shadow root
    shadowRoot.innerHTML = `
      <style>
        .card {
          border: 1px solid #007bff; /* Different border color */
          padding: 20px;
          border-radius: 10px;
          box-shadow: 3px 3px 10px rgba(0,123,255,0.2);
          font-family: Arial, sans-serif;
          background-color: #e9f5ff;
        }
        h3 {
          color: #0056b3;
          margin-top: 0;
        }
        p {
          color: #444;
          line-height: 1.6;
        }
      </style>
      <div class="card">
        <h3>Shadow DOM Karte</h3>
        <p>Die Stile dieser Karte sind vollständig mit Shadow DOM gekapselt.</p>
      </div>
    `;
  }
}

customElements.define('my-shadow-card', MyShadowCard);

Wenn Sie nun <code><my-shadow-card></my-shadow-card></code> verwenden, werden Sie sehen, dass die internen Stilregeln unabhängig vom Rest der Seite funktionieren. <code>mode: 'open'</code> bedeutet, dass Sie mit JavaScript auf das Shadow DOM zugreifen können; im <code>'closed'</code>-Modus ist kein Zugriff möglich.

Slots: Dynamische Inhaltsverteilung

Was aber, wenn wir dynamischen Inhalt von außen in unsere Komponente einfügen möchten? Zum Beispiel, wenn der Titel oder Inhalt der Karte bei jeder Verwendung anders sein wird? Hier kommt das HTML-Element <code><slot></code> ins Spiel. Slots ermöglichen es Ihnen, Inhalte, die von außerhalb des Shadow DOM kommen, an bestimmten Stellen innerhalb des Shadow-Baums Ihrer Komponente zu platzieren.


class MySlottedCard extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = `
      <style>
        .card {
          border: 1px dashed #28a745; /* Different border style */
          padding: 15px;
          margin-bottom: 10px;
          border-radius: 5px;
          background-color: #f0fff4;
        }
        ::slotted(h3) { /* Styling content passed through slots */
          color: #218838;
          font-size: 1.5em;
        }
        ::slotted(p) {
          color: #333;
        }
      </style>
      <div class="card">
        <slot name="card-title"><h3>Standardtitel</h3></slot>
        <slot><p>Standardinhalt.</p></slot>
        <footer><small>Erstellt mit Web Component.</small></footer>
      </div>
    `;
  }
}

customElements.define('my-slotted-card', MySlottedCard);

Wenn Sie diese Komponente verwenden, können Sie den Inhalt entsprechend den Slot-Namen platzieren:


<my-slotted-card>
  <h3 slot="card-title">Benutzerdefinierter Kartentitel</h3>
  <p>Der Inhalt dieser Karte kommt von außen.</p>
  <p>Dank Slots haben wir eine flexible Struktur.</p>
</my-slotted-card>

<my-slotted-card>
  <h3 slot="card-title">Ein anderer Titel</h3>
  <p>Kann nur mit einem Absatz verwendet werden.</p>
</my-slotted-card>

<my-slotted-card>
  <!-- Nur Standardinhalt verwenden -->
</my-slotted-card>

<code><slot></code>-Tags können mit dem Attribut <code>name</code> benannt werden. Ein unbenanntes <code><slot></code> (Standard-Slot) erfasst alle Inhalte, die nicht benannten Slots zugewiesen sind. Sie können auch Standardinhalte in einem <code><slot></code> hinzufügen, um festzulegen, was angezeigt werden soll, wenn von außen nichts bereitgestellt wird.

Erweiterte Nutzung und Best Practices

  • Lifecycle Callbacks: Custom Elements verfügen über Lifecycle-Methoden. Zum Beispiel wird <code>connectedCallback()</code> ausgeführt, wenn die Komponente dem DOM hinzugefügt wird, und <code>disconnectedCallback()</code>, wenn sie entfernt wird. Beispiel:
    
    class MyLifecycleElement extends HTMLElement {
      connectedCallback() {
        console.log('Komponente dem DOM hinzugefügt.');
        // Event-Listener können hier hinzugefügt werden.
      }
    
      disconnectedCallback() {
        console.log('Komponente aus dem DOM entfernt.');
        // Event-Listener können hier bereinigt werden.
      }
    }
    customElements.define('my-lifecycle-element', MyLifecycleElement);
    
  • Attribute vs. Properties: HTML-Attribute sind String-Werte und werden im DOM widergespiegelt. JavaScript-Eigenschaften können beliebigen Typs sein und werden direkt auf dem Elementobjekt gehalten. Um auf Attributänderungen zu reagieren, können Sie <code>static get observedAttributes()</code> und die Methoden <code>attributeChangedCallback(name, oldValue, newValue)</code> verwenden.
  • Styling von Web Components: Stile innerhalb des Shadow DOM sind gekapselt und können nicht direkt von außen aufgerufen werden. Mit <code>::part()</code> CSS-Selektoren können jedoch bestimmte interne Elemente von außen gestylt werden. Sie können auch Stilparameter von außerhalb der Komponente mithilfe von <code>CSS Custom Properties (CSS-Variablen)</code> übergeben.

Fazit

Web Components bieten mit Custom Elements, Shadow DOM und Slots einen leistungsstarken Standard in der modernen Webentwicklung. Dank Kapselung, Wiederverwendbarkeit und Framework-Unabhängigkeit ermöglichen sie Ihnen, nachhaltigere, performantere und interoperablere Webanwendungen zu erstellen. Insbesondere bei großen Projekten oder in Situationen, in denen mehrere Projekte dieselben UI-Komponenten verwenden müssen, werden Web Components zu einem unverzichtbaren Werkzeug. Das Erlernen dieser Technologie wird Ihre Frontend-Architektur auf die nächste Ebene heben.

Zurück zum Blog

Kommentare (0)

Noch keine Kommentare. Seien Sie der Erste!

Kommentar absenden