Web components

Manchmal setzen wir web-components ein. Eine Technologie um, unabhängig von großen Frameworks wie React oder Vue, kleine Komponenten für Webseiten zu bauen. Hier eine kurze Einführung:

Was sind Web components?

Web-Components sind eine Sammlung aus vier Standards:

Kurz gesagt, setzt eine Web Komponente diese 4 Werkzeuge sinnvoll ein, um wiederverwendbare Bausteine für Webseiten zu bauen.

Eine neue Komponente…

Der Schlüssel zu einer neuen Web Komponente ist das Attribut window.customElements. Mit ihm kann man eine neue Komponente definieren. Dazu schreibt man eine Klasse, z.B. DropDown, wir zeigen gleich wie, und registriert sie als Web Komponente:

window.customElements.define('drop-down', DropDown)

Der erste Parameter ist natürlich der Name des Tag. Er muss einen Bindestrich enthalten.

… und ihre Implementierung

Die Klasse für die Komponente sieht nicht allzu kompliziert aus. Sie wird von HTMLElementabgeleitet:

class DropDown extends HTMLElement {

  constructor() {
    super();
  }

Wir geben Ihr noch ein Attribut - damit kann sie dann z.B. so genutzt werden: <drop-down name="test" />:

  set name(option) {
    this.setAttribute("name", option);
  }
 
  get name() {
    return this.hasAttribute("name");
  }

Wenn die Komponente in die Seite eingefügt wird, wird dieser Callback aufgerufen. Er fügt dem DOM zunächst ein Shadow-DOM hinzu und befüllt diesen dann. Dazu wird ganz einfach ein interpolierter JavaScript-String eingesetzt.

    connectedCallback() {
        let shadowDom = this.attachShadow({ mode: "open" })
        shadowDom.innerHTML = `
            <select name="${this.name}>
                <option>1</option>
                <option>2</option>
            </select>
        `;
    }
}

… fertig!

Und was ist mit den Templaten?

Das mit dem JavaScript String ist so eine Sache… Natürlich mischt man damit Code und Darstellung. Eine Alternative wäre die Nutzung von HTML-Templaten, die in die HTML-Seite eingebettet und in der Komponente referenziert werden. Aber das zerstört natürlich die Kapselung: Das Templat soll ja Teil der Komponente und nicht der Seite sein.

Das Beste ist also, die Komponente nicht in einer JavaScript-Datei, sondern in einer HTML-Datei unterzubringen, die so aussieht:

<template id="my-drop-down">
    <select name="${this.name}>
        <option>1</option>
        <option>2</option>
    </select>
</template>

<script>
class DropDown extends HTMLElement {
    ....
}
window.customElements.define('drop-down', DropDown)
</script>

Der Callback muss dann nur folgendermaßen umgeschrieben werden:

    connectedCallback() {
        let shadowDom = this.attachShadow({ mode: "open" });
        let template = document.getElementById("my-drop-down");
        let templateHtml = template.content.cloneNode(true);
        shadowDom.appendChild(templateHtml);
        let select = shadowDom.getElementByTagName('select')[0]
        select.setAttribute('name', this.name())
    }

Muss ich das echt selbst machen?

Naja… das ist ja der Zweck…

Aber keine Angst, auf webcomponents.org gibt es massenhaft fertige Komponenten, einfach mal reinschauen!

Und dann gibt es noch Polymer, dessen Projekt lit-element den Umgang mit Web Komponenten etwas einfacher gestaltet.