Benutzerdefinierte Elemente sind stellen die Möglichkeit bereit, benutzerdefinierte HTML-Elements zu schaffen. Sie können eigenes durch JavaScript beschriebenes Verhalten und CSS-Styling haben. Sie sind Teil der Web-Components, können aber auch unabhängig von diesen benutzt werden.

Note: Benutzerdefinierte Elemente gelten erst seit Kurzem als stabil definiert und Teile des MDN weisen Dokumentation für veraltete APIs früherer Spezifikationsentwürfe auf.

Obwohl es bereits möglich war, benutzerdefinierte Tag-Namen wie <mytag> zu schaffen, sie mit CSS zu stylen und via JavaScript ihr Verhalten zu beschreiben, haben benutzerdefinierte Elemente ihre Daseinsberechtigung. Ihr großer Vorteil ist das Vorhandensein so genannter Lebenszyklus-Reaktionen, die es erlauben, Methoden zu bestimmten Momenten des "Lebenszyklus" des Elementes aufzurufen. So kann beispielsweise Verhalten beschrieben werden, dass ausgeführt wird, wenn das Element dem DOM hinzugefügt wird ("connected"), wenn es aus diesem entfernt wird ("disconnected") oder sich seine Attribute ändern.

Die Schlüsselmethode für benutzerdefinierte Elemente ist die CustomElementRegistry.define()-Methode, die benutzt werden kann, um ein neues benutzerdefinierte Elemente zu erschaffen. Dieses neue Element wird dann für jede seiner Instanzen diese neue Klasse anstelle des standardmäßig verwendeten HTMLUnknownElement benutzen. Benutzerdefinierte Elemente können auch auf nativen Elementen wie  <button> basieren, indem sie folgende Syntax benutzen: <button is="my-button"> Sie werden dann benutzerdefinierte eingebaute Elemente genannt.

Methoden benutzerdefinierter Elemente

Benutzerdefinierte Elemente besitzen folgende Methoden:

constructor()
Wird aufgerufen, wenn eine Element erzeugt und erweitert wird.
connectedCallback()
Wird aufgerufen, wenn das Element in das Dokument eingefügt wird, auch wenn es nur der Shadow Tree ist
disconnectedCallback()
Wird aufgerufen, wenn das Element aus dem Dokument entfernt wird.
attributeChangedCallback(attributeName, oldValue, newValue, namespace)
Wird aufgerufen, wenn Attribute des Elements geändert, angefügt, entfernt oder ersetzt werden. Wird nur für beobachtete Attribute aufgerufen.
adoptedCallback(oldDocument, newDocument)
Wird aufgerufen, wenn das Element in ein neues Dokument übernommen wird.

Beispiele

Benutzerdefinierte Elemente müssen die class Syntax benutzen, die in neueren JavaScript-Versionen bereit steht.

HTML-Datei:

Wenn unter diesem Text nichts steht, unterstützt ihr Browser keine benutzerdefinierten Elemente.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="http://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="http://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="http://example.com/3"></x-product>

JS-Datei:

// Klasse für das Element erzeugen
class XProduct extends HTMLElement {
  constructor() {
    // super() muss immer als erstes im Konstruktor aufgerufen werden
    super();

    // Shadow-Root erzeugen
    var shadow = this.attachShadow({mode: 'open'});

    // Standard img-Element erzeugen und Attribute setzen
    var img = document.createElement('img');
    img.alt = this.getAttribute('data-name');
    img.src = this.getAttribute('data-img');
    img.width = '150';
    img.height = '150';
    img.className = 'product-img';

    // Bild der Shadow-Root hinzufügen.
    shadow.appendChild(img);

    // Event-Listener zum Bild hinzufügen.
    img.addEventListener('click', () => {
      window.location = this.getAttribute('data-url');
    });

    // Link zum Produkt erzeugen.
    var link = document.createElement('a');
    link.innerText = this.getAttribute('data-name');
    link.href = this.getAttribute('data-url');
    link.className = 'product-name';

    // Link der Shadow-Root hinzufügen.
    shadow.appendChild(link);
  }
}

// Neues Element definieren
customElements.define('x-product', XProduct);

CSS-Datei:

body {
  background: #F7F7F7;
}

x-product {
  display: inline-block;
  float: left;
  margin: 0.5em;
  border-radius: 3px;
  background: #FFF;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  font-family: Helvetica, arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

x-product::slotted(.product-img) {
  cursor: pointer;
  background: #FFF;
  margin: 0.5em;
}

x-product::slotted(.product-name) {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #08C;
  border-top: 1px solid #EEE;
  font-weight: bold;
  padding: 0.75em 0;
}

Unten kann das Live-Beispiel des obigen Codes gesehen werden:

Beobachtete Attribute

Um benachrichtigt zu werden, wenn Attribute verändert werden, muss eine Liste von beobachteten Attributen bei der Initialisierung des Elements angelegt werden, in dem eine statische observedAttributes get-Methode der Klasse des Elementes hinzugefügt wird, die ein Array mit den entsprechenden Attributsnamen zurückgibt.

JS-Datei:

class HelloElement extends HTMLElement {
  // Das 'name'-Attribut beobachten.
  static get observedAttributes() {return ['name']; }

  // Auf Attributsänderungen reagieren.
  attributeChangedCallback(attr, oldValue, newValue) {
    if (attr == 'name') {
      this.textContent = `Hello, ${newValue}`;
    }
  }
}

// Neues Element definieren
customElements.define('hello-element', HelloElement);

HTML-Datei:

<hello-element name="Anita"></hello-element>

Unten kann das Live-Beispiel des obigen Codes gesehen werden:

Spezifikationen

Benutzerdefinierte Elemente sind in der folgenden Spezifikation definiert:

Spezifikation Status Kommentar
The HTML Standard: Custom elements LS  

Browserkompatibilität

Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
Grundlegende Unterstützung Nicht unterstützt 59.0 Nicht unterstützt 47.0 10.1
Benutzerdefinierte eingebaute Elemente Nicht unterstützt 59.0 Nicht unterstützt 47.0 Nicht unterstützt
Feature Firefox Mobile (Gecko) Chrome for Android IE Mobile Opera Mobile Safari Mobile
Grundlegende Unterstützung Nicht unterstützt 56.0 Nicht unterstützt 47.0 10.1
Benutzerdefinierte eingebaute Elemente Nicht unterstützt 56.0 Nicht unterstützt 47.0 Nicht unterstützt

1. Firefox hat eine "dom.webcomponents.enabled"-Eigenschaft in about:config, dennoch ist sind benutzerdefinierte Elemente nicht verfügbar, wenn diese auf true gesetzt wurde.

Resources

Schlagwörter des Dokuments und Mitwirkende

 Mitwirkende an dieser Seite: amelzer
 Zuletzt aktualisiert von: amelzer,