Wir alle haben Projekte, an denen wir lieber nicht arbeiten würden. Der Code ist unüberschaubar geworden, der Umfang hat sich entwickelt, schnelle Korrekturen wurden auf andere Korrekturen angewandt und die Struktur ist unter dem Gewicht des Spaghetticodes zusammengebrochen. Coding kann eine chaotische Angelegenheit sein.

Projekte profitieren von der Verwendung einfacher, unabhängiger Module, die eine einzige Verantwortung haben. Modularer Code ist gekapselt, so dass man sich weniger Gedanken über die Implementierung machen muss. Solange du weißt, was ein Modul ausgibt, wenn es eine Reihe von Eingaben erhält, musst du nicht unbedingt verstehen, wie es dieses Ziel erreicht.

Die Anwendung von modularen Konzepten auf eine einzelne Programmiersprache ist einfach, aber die Webentwicklung erfordert eine vielfältige Mischung von Technologien. Browser analysieren HTML, CSS und JavaScript, um den Inhalt, die Stile und die Funktionalität der Seite darzustellen.

Sie lassen sich nicht immer leicht mischen, denn:

  • Zusammenhängender Code kann auf drei oder mehr Dateien aufgeteilt sein, und
  • Globale Stile und JavaScript-Objekte können sich auf unerwartete Weise gegenseitig beeinträchtigen.

Diese Probleme treten zusätzlich zu denen auf, die durch Sprachlaufzeiten, Frameworks, Datenbanken und andere auf dem Server verwendete Abhängigkeiten entstehen.

Schau dir unseren Video-Leitfaden zu Webkomponenten an


Was sind Webkomponenten?

Eine Webkomponente ist eine Möglichkeit, einen gekapselten Codeblock mit einer einzigen Verantwortlichkeit zu erstellen, der auf jeder Seite wiederverwendet werden kann.

Betrachte den HTML <video> Tag. Anhand einer URL kann ein Betrachter Steuerelemente wie Abspielen, Pause, Zurückgehen, Vorwärtsgehen und Einstellen der Lautstärke verwenden.

Styling und Funktionalität sind vorgegeben, obwohl du mit verschiedenen Attributen und JavaScript API-Aufrufen Modifikationen vornehmen kannst. Eine beliebige Anzahl von <video>-Elementen kann innerhalb anderer Tags platziert werden, und sie werden nicht in Konflikt geraten.

Was ist, wenn du deine eigene Funktionalität benötigst? Zum Beispiel ein Element, das die Anzahl der Wörter auf der Seite anzeigt? Es gibt (noch) kein HTML <wordcount> Tag.

Frameworks wie React und Vue.js erlauben es Entwicklern, Webkomponenten zu erstellen, bei denen der Inhalt, das Styling und die Funktionalität in einer einzigen JavaScript-Datei definiert werden können. Diese lösen viele komplexe Programmierprobleme, aber bedenke, dass:

  • Du musst lernen, wie man dieses Framework benutzt und deinen Code aktualisieren, wenn es sich weiterentwickelt.
  • Eine Komponente, die für ein Framework geschrieben wurde, ist selten mit einem anderen kompatibel.
  • Frameworks steigen und sinken in ihrer Popularität. Du wirst abhängig von den Launen und Prioritäten des Entwicklungsteams und der Benutzer.
  • Standard Web Components können Browserfunktionalität hinzufügen, die mit JavaScript allein nur schwer zu erreichen ist (wie z.B. das Shadow DOM).

Glücklicherweise finden beliebte Konzepte, die in Bibliotheken und Frameworks eingeführt werden, ihren Weg in die Webstandards. Es hat einige Zeit gedauert, aber Web Components sind angekommen.

Eine kurze Geschichte der Web Components

Nach vielen herstellerspezifischen Fehlstarts wurde das Konzept der Standard Web Components erstmals von Alex Russell auf der Fronteers Conference 2011 vorgestellt. Googles Polymer-Bibliothek (ein Polyfill, das auf den aktuellen Vorschlägen basiert) kam zwei Jahre später, aber frühe Implementierungen erschienen erst 2016 in Chrome und Safari.

Die Browserhersteller brauchten Zeit, um die Details auszuhandeln, aber die Web Components wurden 2018 in Firefox und 2020 in Edge hinzugefügt (als Microsoft auf die Chromium-Engine umstieg).

Verständlicherweise waren nur wenige Entwickler bereit oder in der Lage, Web Components zu übernehmen, aber wir haben endlich ein gutes Niveau an Browser Support mit stabilen APIs erreicht. Nicht alles ist perfekt, aber sie sind eine zunehmend brauchbare Alternative zu Framework-basierten Komponenten.

Selbst wenn du noch nicht bereit bist, deinen Favoriten aufzugeben, sind Web Components mit jedem Framework kompatibel und die APIs werden auch in den nächsten Jahren unterstützt.

Es gibt Repositories mit vorgefertigten Web Components, die jeder ausprobieren kann:

…aber es macht mehr Spaß, seinen eigenen Code zu schreiben!

Dieses Tutorial bietet eine komplette Einleitung in Web Components, die ohne ein JavaScript-Framework geschrieben wurden. Du wirst lernen, was sie sind und wie du sie für deine Webprojekte anpassen kannst. Du wirst einige Kenntnisse in HTML5, CSS und JavaScript benötigen.

Erste Schritte mit Web Components

Web Components sind benutzerdefinierte HTML-Elemente wie z.B. <hello-world></hello-world>. Der Name muss einen Bindestrich enthalten, um nicht mit Elementen zu kollidieren, die offiziell von der HTML-Spezifikation unterstützt werden.

Du musst eine ES2015-Klasse definieren, um das Element zu steuern. Es kann beliebig benannt werden, aber HelloWorld ist gängige Praxis. Es muss das HTMLElement Interface erweitern, welches die Standardeigenschaften und -methoden jedes HTML-Elements repräsentiert.

Hinweis: Firefox erlaubt es dir, bestimmte HTML-Elemente wie HTMLParagraphElement, HTMLImageElement oder HTMLButtonElement zu erweitern. Dies wird in anderen Browsern nicht unterstützt und erlaubt es dir nicht, ein Schatten-DOM zu erstellen.

Um etwas Nützliches zu tun, benötigt die Klasse eine Methode namens connectedCallback(), die aufgerufen wird, wenn das Element zu einem Dokument hinzugefügt wird:

class HelloWorld extends HTMLElement {

  // Komponente verbinden
  connectedCallback() {
    this.textContent = 'Hello World!';
  }

}

In diesem Beispiel wird der Text des Elements auf „Hello World“ gesetzt.

Die Klasse muss bei der CustomElementRegistry registriert werden, um sie als Handler für ein bestimmtes Element zu definieren:

customElements.define( 'hello-world', HelloWorld );

Der Browser assoziiert nun das <hello-world> Element mit deiner HelloWorld Klasse, wenn dein JavaScript geladen wird (z.B.<script type="module" src="./helloworld.js"></script>).

Du hast jetzt ein eigenes Element!

CodePen demonstration

Diese Komponente kann in CSS wie jedes andere Element gestaltet werden:

hello-world {
  font-weight: bold;
  color: red;
}

Hinzufügen von Attributen

Diese Komponente ist nicht vorteilhaft, da immer der gleiche Text ausgegeben wird. Wie jedes andere Element auch, können wir HTML-Attribute hinzufügen:

<hello-world name="Craig"></hello-world>

Damit könnte der Text überschrieben werden, so dass „Hello Craig!“ angezeigt wird. Um dies zu erreichen, kannst du der HelloWorld Klasse eine constructor() Funktion hinzufügen, die ausgeführt wird, wenn jedes Objekt erstellt wird. Das muss sie:

  1. rufe die super()-Methode auf, um das übergeordnete HTMLElement zu initialisieren, und
  2. andere Initialisierungen vorzunehmen. In diesem Fall definieren wir eine name-Eigenschaft, die auf den Standardwert „World“ gesetzt wird:
class HelloWorld extends HTMLElement {

  constructor() {
    super();
    this.name = 'World';
  }

  // more code...

Deine Komponente interessiert sich nur für das Attribut name. Eine statische observedAttributes() Eigenschaft sollte ein Array von zu beobachtenden Eigenschaften zurückgeben:

// component attributes
static get observedAttributes() {
  return ['name'];
}

Eine attributeChangedCallback() Methode wird aufgerufen, wenn ein Attribut im HTML definiert oder mit JavaScript geändert wird. Ihr werden der Name der Eigenschaft, der alte und der neue Wert übergeben:

// attribute change
attributeChangedCallback(property, oldValue, newValue) {

  if (oldValue === newValue) return;
  this[ property ] = newValue;

}

In diesem Beispiel würde nur die Eigenschaft name aktualisiert werden, aber du könntest bei Bedarf weitere Eigenschaften hinzufügen.

Zum Schluss musst du noch die Nachricht in der Methode connectedCallback() anpassen:

// connect component
connectedCallback() {

  this.textContent = `Hello ${ this.name }!`;

}

CodePen demonstration

Lebenszyklus-Methoden

Der Browser ruft automatisch sechs Methoden während des Lebenszyklus des Web Component Status auf. Die vollständige Liste findest du hier, obwohl du die ersten vier bereits in den Beispielen oben gesehen hast:

constructor()

Es wird aufgerufen, wenn die Komponente zum ersten Mal initialisiert wird. Es muss super() aufrufen und kann alle Voreinstellungen setzen oder andere Vorverarbeitungsprozesse durchführen.

static observedAttributes()

Gibt ein Array von Attributen zurück, die der Browser beobachten wird.

attributeChangedCallback(propertyName, oldValue, newValue)

Wird immer dann aufgerufen, wenn ein beobachtetes Attribut geändert wird. Diejenigen, die in HTML definiert sind, werden sofort übergeben, aber JavaScript kann sie modifizieren:

document.querySelector('hello-world').setAttribute('name', 'Everyone');

Die Methode muss eventuell ein Re-Rendering auslösen, wenn dies geschieht.

connectedCallback()

Diese Funktion wird aufgerufen, wenn die Webkomponente an ein Document Object Model angehängt wird. Es sollte jedes erforderliche Rendering ausführen.

disconnectedCallback()

Es wird aufgerufen, wenn die Webkomponente von einem Document Object Model entfernt wird. Dies kann nützlich sein, wenn du aufräumen musst, wie z.B. das Entfernen von gespeicherten Zuständen oder das Abbrechen von Ajax Anfragen.

adoptedCallback()

Diese Funktion wird aufgerufen, wenn eine Webkomponente von einem Dokument in ein anderes verschoben wird. Vielleicht findest du eine Verwendung dafür, obwohl ich mich schwer getan habe, an irgendwelche Fälle zu denken!

Wie Webkomponenten mit anderen Elementen interagieren

Web Components bieten einige einzigartige Funktionen, die du in JavaScript Frameworks nicht finden wirst.

Das Schatten-DOM

Obwohl die Webkomponente, die wir oben gebaut haben, funktioniert, ist sie nicht immun gegen Eingriffe von außen, und CSS oder JavaScript könnten sie verändern. Ebenso könnten die Stile, die du für deine Komponente definierst, nach außen dringen und andere beeinflussen.

Das Shadow DOM löst dieses Kapselungsproblem, indem es ein separates DOM an die Webkomponente mit anhängt:

const shadow = this.attachShadow({ mode: 'closed' });

Der Modus kann entweder sein:

  1. „open“ — JavaScript in der äußeren Seite kann auf das Shadow DOM zugreifen (mit Element.shadowRoot), oder
  2. „closed“ — auf das Shadow DOM kann nur innerhalb der Webkomponente zugegriffen werden.

Das Shadow DOM kann wie jedes andere DOM-Element manipuliert werden:

connectedCallback() {

  const shadow = this.attachShadow({ mode: 'closed' });

  shadow.innerHTML = `
    <style>
      p {
        text-align: center;
        font-weight: normal;
        padding: 1em;
        margin: 0 0 2em 0;
        background-color: #eee;
        border: 1px solid #666;
      }
    </style>

    <p>Hello ${ this.name }!</p>`;

}

Die Komponente rendert nun den „Hello“-Text innerhalb eines <p>-Elements und stylt ihn. Es kann nicht durch JavaScript oder CSS außerhalb der Komponente verändert werden, obwohl einige Stile wie die Schriftart und Farbe von der Seite geerbt werden, da sie nicht explizit definiert wurden.

CodePen demonstration

Die Stile, die auf diese Webkomponente skaliert sind, können keine anderen Absätze auf der Seite oder sogar andere <hello-world> Komponenten beeinflussen.

Beachte, dass der CSS :host Selektor das äußere <hello-world> -Element innerhalb der Webkomponente stylen kann:

:host {
  transform: rotate(180deg);
}

Du kannst auch Stile festlegen, die angewendet werden, wenn das Element eine bestimmte Klasse verwendet, z.B. <hello-world class="rotate90">:

:host(.rotate90) {
  transform: rotate(90deg);
}

HTML Templates

HTML innerhalb eines Skripts zu definieren, kann für komplexere Web Components unpraktisch werden. Ein Template erlaubt es dir, einen Teil von HTML in deiner Seite zu definieren, den deine Webkomponente verwenden kann. Dies hat mehrere Vorteile:

  1. Du kannst den HTML-Code anpassen, ohne Strings in deinem JavaScript umschreiben zu müssen.
  2. Komponenten können angepasst werden, ohne dass du für jeden Typ separate JavaScript-Klassen erstellen musst.
  3. Es ist einfacher, HTML in HTML zu definieren – und es kann auf dem Server oder Client geändert werden, bevor die Komponente gerendert wird.

Templates werden in einem <template>-Tag definiert, und es ist praktisch, eine ID zuzuweisen, damit du es innerhalb der Komponentenklasse referenzieren kannst. In diesem Beispiel drei Absätze, um die „Hello“-Nachricht anzuzeigen:

<template id="hello-world">

  <style>
    p {
      text-align: center;
      font-weight: normal;
      padding: 0.5em;
      margin: 1px 0;
      background-color: #eee;
      border: 1px solid #666;
    }
  </style>

  <p class="hw-text"></p>
  <p class="hw-text"></p>
  <p class="hw-text"></p>

</template>

Die Web Component Klasse kann auf dieses Template zugreifen, seinen Inhalt abrufen und die Elemente klonen, um sicherzustellen, dass du überall, wo es verwendet wird, ein einzigartiges DOM-Fragment erstellst:

const template = document.getElementById('hello-world').content.cloneNode(true);

Das DOM kann verändert und direkt zum Shadow DOM hinzugefügt werden:

connectedCallback() {

  const

    shadow = this.attachShadow({ mode: 'closed' }),
    template = document.getElementById('hello-world').content.cloneNode(true),
    hwMsg = `Hello ${ this.name }`;

  Array.from( template.querySelectorAll('.hw-text') )
    .forEach( n => n.textContent = hwMsg );

  shadow.append( template );

}

CodePen demonstration

Template Slots

Slots erlauben es dir, ein Template anzupassen. Angenommen, du möchtest deine <hello-world> Webkomponente verwenden, aber die Nachricht innerhalb einer <h1> Überschrift im Shadow DOM platzieren. Du könntest diesen Code schreiben:

<hello-world name="Craig">

  <h1 slot="msgtext">Hello Default!</h1>

</hello-world>

(Beachte das slot-Attribut.)

Optional könntest du weitere Elemente hinzufügen, wie zum Beispiel einen weiteren Absatz:

<hello-world name="Craig">

  <h1 slot="msgtext">Hello Default!</h1>
  <p>This text will become part of the component.</p>

</hello-world>

Die Slots können nun innerhalb deines Templates implementiert werden:

<template id="hello-world">

  <slot name="msgtext" class="hw-text"></slot>

  <slot></slot>

</template>

Ein Element-Slot-Attribut, das auf „msgtext“ gesetzt ist (das <h1>), wird an der Stelle eingefügt, an der es einen <slot> namens „msgtext“ gibt. Dem <p> wird kein Slotname zugewiesen, aber es wird im nächsten verfügbaren unbenannten <slot> verwendet. Im Endeffekt wird das Template zu:

<template id="hello-world">

  <slot name="msgtext" class="hw-text">
    <h1 slot="msgtext">Hello Default!</h1>
  </slot>

  <slot>
    <p>This text will become part of the component.</p>
  </slot>

</template>

Ganz so einfach ist es in der Realität nicht. Ein <slot> Element im Shadow DOM zeigt auf die eingefügten Elemente. Du kannst nur auf sie zugreifen, indem du einen <slot> lokalisierst und dann die Methode .assignedNodes() benutzt, um ein Array der inneren Kinder zurückzugeben. Die aktualisierte connectedCallback() Methode:

connectedCallback() {

  const
    shadow = this.attachShadow({ mode: 'closed' }),
    hwMsg = `Hello ${ this.name }`;

  // append shadow DOM
  shadow.append(
    document.getElementById('hello-world').content.cloneNode(true)
  );

  // Finde alle Slots mit einer hw-text Klasse
  Array.from( shadow.querySelectorAll('slot.hw-text') )

    // ersten zugewiesenenNode im Slot aktualisieren
    .forEach( n => n.assignedNodes()[0].textContent = hwMsg );

}

CodePen demonstration

Darüber hinaus kannst du die eingefügten Elemente nicht direkt stylen, obwohl du bestimmte Slots innerhalb deiner Webkomponente anvisieren kannst:

<template id="hello-world">

  <style>
    slot[name="msgtext"] { color: green; }
  </style>

  <slot name="msgtext" class="hw-text"></slot>
  <slot></slot>

</template>

Template-Slots sind ein wenig ungewöhnlich, aber ein Vorteil ist, dass dein Inhalt angezeigt wird, wenn JavaScript nicht ausgeführt werden kann. Dieser Code zeigt eine Standardüberschrift und einen Absatz, die nur ersetzt werden, wenn die Web Component Klasse erfolgreich ausgeführt wird:

<hello-world name="Craig">

  <h1 slot="msgtext">Hello Default!</h1>
  <p>This text will become part of the component.</p>

</hello-world>

Du könntest also eine Form der progressiven Erweiterung implementieren – selbst wenn es nur eine „Du brauchst JavaScript„-Meldung ist!

Das deklarative Shadow DOM

Die obigen Beispiele konstruieren ein Shadow DOM mit JavaScript. Das bleibt die einzige Option, aber ein experimentelles deklaratives Shadow DOM wird für Chrome entwickelt. Dies ermöglicht Server-Side Rendering und vermeidet jegliche Layout-Verschiebungen oder das Aufblitzen von unstylisiertem Inhalt.

Der folgende Code wird vom HTML-Parser erkannt und erzeugt ein identisches Shadow DOM wie das, das du im letzten Abschnitt erstellt hast (du müsstest die Meldung bei Bedarf aktualisieren):

<hello-world name="Craig">

  <template shadowroot="closed">
    <slot name="msgtext" class="hw-text"></slot>
    <slot></slot>
  </template>

  <h1 slot="msgtext">Hallo Standard!</h1>
  <p>Dieser Text wird Teil der Komponente.</p>

</hello-world>

Das Feature ist nicht in allen Browsern verfügbar und es gibt keine Garantie, dass es Firefox oder Safari erreichen wird. Du kannst mehr über das deklarative Shadow DOM herausfinden, und ein Polyfill ist einfach, aber sei dir bewusst, dass sich die Implementierung ändern könnte.

Shadow DOM Ereignisse

Deine Webkomponente kann Ereignisse an jedes Element im Shadow DOM anhängen, genau wie du es im Seiten-DOM tun würdest, z.B. um auf Klick-Ereignisse auf allen inneren Kindern zu hören:

shadow.addEventListener('click', e => {

  // etwas tun

});

Solange du die Propagation nicht stoppst, wird das Ereignis in das Seiten-DOM sprudeln, aber das Ereignis wird zurückgesendet. Daher scheint es von deinem benutzerdefinierten Element zu kommen und nicht von Elementen innerhalb des Elements.

Verwendung von Web Components in anderen Frameworks

Jede Webkomponente, die du erstellst, wird in allen JavaScript Frameworks funktionieren. Keines von ihnen kennt oder kümmert sich um HTML-Elemente – deine <hello-world> Komponente wird identisch mit einem <div> behandelt und im DOM platziert, wo die Klasse aktiviert wird.

custom-elements-everywhere.com bietet eine Liste von Frameworks und Web Component Notes. Die meisten sind vollständig kompatibel, obwohl React.js einige Herausforderungen hat. Es ist möglich, <hello-world> in JSX zu verwenden:

import React from 'react';
import ReactDOM from 'react-dom';
import from './hello-world.js';

function MeineSeite() {

  return (
    <>
      <hello-world name="Craig"></hello-world> 
    </>
  );

}

ReactDOM.render(<MyPage />, document.getElementById('root'));

…aber:

  • React kann nur primitive Datentypen an HTML-Attribute übergeben (keine Arrays oder Objekte).
  • React kann nicht auf Web Component Events lauschen, daher musst du manuell deine eigenen Handler anhängen.

Web Component Kritikpunkte und Probleme

Web Components haben sich deutlich verbessert, aber einige Aspekte können knifflig zu handhaben sein.

Styling-Schwierigkeiten

Das Styling von Web Components birgt einige Herausforderungen, besonders wenn du scoped Styles überschreiben willst. Es gibt viele Lösungen:

  1. Vermeide die Verwendung des Shadow DOMs. Du könntest Inhalte direkt an dein benutzerdefiniertes Element anhängen, obwohl jedes andere JavaScript es versehentlich oder böswillig verändern könnte.
  2. Verwende die :host Klassen. Wie wir oben gesehen haben, kann scoped CSS bestimmte Stile anwenden, wenn eine Klasse auf das benutzerdefinierte Element angewendet wird.
  3. Schau dir die benutzerdefinierten CSS-Eigenschaften (Variablen) an. Benutzerdefinierte Eigenschaften kaskadieren in Web Components. Wenn dein Element also var(--my-color) verwendet, kannst du --my-color in einem äußeren Container (wie :root) setzen und es wird verwendet.
  4. Nutze die Vorteile von shadow parts. Der neue ::part() Selektor kann eine innere Komponente stylen, die ein part-Attribut hat, d.h. <h1 part="heading"> innerhalb einer <hello-world> Komponente kann mit dem Selektor hello-world::part(heading) gestylt werden.
  5. Übergib eine Zeichenkette mit Stilen. Du kannst sie als Attribut übergeben, um sie innerhalb eines <style> Blocks anzuwenden.

Keine ist ideal und du musst sorgfältig planen, wie andere Benutzer deine Webkomponente anpassen können.

Ignorierte Eingaben

Alle <input>, <textarea>, oder <select> -Felder in deinem Schatten-DOM werden nicht automatisch mit dem enthaltenen Formular verbunden. Frühe Web Component-Anhänger fügten versteckte Felder zum Seiten-DOM hinzu oder nutzten die FormData-Schnittstelle, um Werte zu aktualisieren. Beides ist nicht besonders praktisch und bricht die Web Component-Kapselung.

Das neue ElementInternals Interface erlaubt es einer Webkomponente, sich in Formulare einzuklinken, so dass eigene Werte und Gültigkeiten definiert werden können. Es ist in Chrome implementiert, aber ein Polyfill ist für andere Browser verfügbar.

Um dies zu demonstrieren, wirst du eine einfache <input-age name="your-age"></input-age>Komponente erstellen. Die Klasse muss einen statischen formAssociated Wert haben, der auf true gesetzt ist und optional kann eine formAssociatedCallback() Methode aufgerufen werden, wenn das äußere Formular assoziiert wird:

// <input-age> web component
class InputAge extends HTMLElement {

  static formAssociated = true;

  formAssociatedCallback(form) {
    console.log('form associated:', form.id);
  }

Der Konstruktor muss nun die attachInternals()-Methode ausführen, die es der Komponente ermöglicht, mit dem Formular und anderem JavaScript-Code zu kommunizieren, der den Wert oder die Validierung überprüfen möchte:

  constructor() {

    super();
    this.internals = this.attachInternals();
    this.setValue('');

  }

  // set form value

  setValue(v) {

    this.value = v;

    this.internals.setFormValue(v);

  }

Die Methode setFormValue() von ElementInternal setzt den Wert des Elements für das übergeordnete Formular, das hier mit einem leeren String initialisiert wird (es kann auch ein FormData Objekt mit mehreren Name/Wert-Paaren übergeben werden). Andere Eigenschaften und Methoden beinhalten:

  • form: das übergeordnete Formular
  • labels: ein Array von Elementen, die die Komponente beschriften
  • Constraint Validation API Optionen wie willValidate, checkValidity, und validationMessage

Die Methode connectedCallback() erstellt wie zuvor ein Shadow DOM, muss aber auch das Feld auf Änderungen überwachen, damit setFormValue() ausgeführt werden kann:

  connectedCallback() {

    const shadow = this.attachShadow({ mode: 'closed' });

    shadow.innerHTML = `
      <style>input { width: 4em; }</style>
      <input type="number" placeholder="age" min="18" max="120" />`;

    // monitor input values
    shadow.querySelector('input').addEventListener('input', e => {
      this.setValue(e.target.value);
    });

  }

Du kannst nun mit dieser Webkomponente ein HTML-Formular erstellen, das sich ähnlich wie andere Formularfelder verhält:

<form id="myform">

  <input type="text" name="your-name" placeholder="name" />

  <input-age name="your-age"></input-age>

  <button>submit</button>

</form>

Es funktioniert, aber es fühlt sich zugegebenermaßen ein wenig umständlich an.

Schau es dir in der CodePen Demonstration an

Weitere Informationen findest du in diesem Artikel über leistungsfähigere Formularsteuerelemente.

Zusammenfassung

Web Components haben es schwer, Zustimmung und Akzeptanz zu erlangen, während JavaScript-Frameworks an Statur und Fähigkeiten gewonnen haben. Wenn du von React, Vue.js oder Angular kommst, können Web Components komplex und klobig wirken, besonders wenn du Features wie Datenbindung und Zustandsverwaltung vermisst.

Es gibt noch einige Probleme zu lösen, aber die Zukunft für Web Components ist rosig. Sie sind Framework-unabhängig, leichtgewichtig, schnell und können Funktionen implementieren, die in JavaScript allein unmöglich wären.

Vor einem Jahrzehnt hätten nur wenige eine Webseite ohne jQuery in Angriff genommen, aber die Browserhersteller haben die exzellenten Teile übernommen und native Alternativen (wie querySelector) hinzugefügt. Das Gleiche wird für JavaScript-Frameworks passieren, und Web Components ist dieser erste zaghafte Schritt.

Hast du noch Fragen zur Verwendung von Web Components? Lass uns in den Kommentaren darüber reden!

Craig Buckler

Freiberuflicher britischer Webentwickler, Autor und Redner. Er ist schon lange dabei und schimpft über Standards und Leistung.