Anzeige
Anzeige

Mit Web Components und Polymer durchstarten: Level up HTML!

Abgesehen von Formularelementen spielt Interaktivität in HTML keine große Rolle. Auch die Frage, wie man UI-Elemente für die Wiederverwendung kapselt, ist nicht abschließend geklärt. Die Antwort könnte Polymer sein, das Bausteine einer Web-Applikation auf Basis der Web-Components-Spezifikation in maßgeschneiderte HTML-Elemente kapselt. Eine Einführung.

7 Min.
Artikel merken
Anzeige
Anzeige

Der Browser dient mittlerweile nicht mehr nur der Darstellung von Dokumenten, sondern vielmehr als Plattform für komplexe Web-Applikationen. Das HTML-Vokabular, das die Auszeichnung klassischer Inhaltstypen wie Überschriften, Absätze, tabellarische Daten und anderes ermöglicht, stößt dabei an seine Grenzen. So gibt es zum Beispiel kein HTML-Element zur semantisch korrekten Auszeichnung eines Image-Sliders. Hier muss man sich mit dem generischen <div>-Element begnügen.

Anzeige
Anzeige

Auch das Einbinden externer Komponenten ist problematisch. Am Beispiel des Image-Sliders bedeutet das: ein solches Modul baut kein Entwickler mehr spezifisch für ein Projekt selbst. Er bindet eine bestehende, externe Lösung ein und parametrisiert diese entsprechend seinen Anforderungen. Dazu muss er mindestens eine JavaScript-Datei und eine CSS-Datei einbinden und möglicherweise auch noch sicherstellen, dass Pfade zu weiteren Assets im Projekt-Kontext korrekt sind. Dieser Aufwand wiederholt sich bei jeder weiteren externen Komponente. Design-affine Entwickler, die nur über ein oberflächliches oder gar kein JavaScript-Verständnis verfügen, stoßen da schnell an ihre Grenzen.

Web Components

Die Web-Components-Spezifikationen, die die Web Platform Working Group des W3C erarbeitet, sollen derlei Probleme beheben. Da frühere, monolithische Ansätze – wie die HTML Components von Microsoft (1998) – gescheitert sind, sollen nun mehrere Browser-APIs spezifiziert werden, die jeweils einen Teil zu dem beitragen, was sich Web Components nennt. Die Browserhersteller können diese APIs nach und nach implementieren [1].

Anzeige
Anzeige

Google – ein Verfechter des Grundsatzes „Das Web als Plattfform“ und treibende Kraft hinter dem Polymer-Projekt – sieht großes Potenzial in den Web Compontents. Seine Hoffnung: Web-App-spezifische, interaktive Elemente auch für weniger programmier-affine Entwickler zugänglich zu machen. Aufwändige Dropdown-Menüs oder Google-Maps sollen dann nicht mehr nur den JavaScript-Profis vorbehalten sein. Die Anpassung der Komponenten erfolgt deklarativ über HTML-Attribute.

Anzeige
Anzeige

Kein Wunder, dass Browser wie Chrome und Opera, die unter anderem auf das von Google betriebene Chromium-Project aufbauen, Web Components bereits voll unterstützen. In den übrigen Browsern müssen Entwickler die Polyfill-Sammlung webcomponents.js [2] einbinden, bevor sie mit eigenen, maßgeschneiderten Elementen beginnen können. Die folgenden vier Komponenten sind Teil der Web-Components-Spezifikationen.

Custom Elements

Das Custom-Element beschreibt die Methode „document.registerElement“, mit der sich das HTML-Vokabular um eigene Elemente erweitern lässt. Zudem können Entwickler damit Methoden und Eigenschaften bestehender HTML-Elemente auf die neuen Elemente vererben und bereits implementierte Funktionalitäten nutzen, ohne das Rad neu erfinden zu müssen. Möchte man etwa sein eigenes Button-Element <my-button> bauen, vererbt man ihm die API des „HTMLButtonElement“ und muss sich daher keine Gedanken über Dinge wie Fokussierbarkeit machen.

Anzeige
Anzeige
Mit Polymer können Frontend-Entwickler die Web Components einfacher einsetzen und sich viel redundanten Code sparen. Die Polymer-Website selbst ist ebenfalls mit Polymer umgesetzt.
Mit Polymer können Frontend-Entwickler die Web Components einfacher einsetzen und sich viel redundanten Code sparen. Die Polymer-Website selbst ist ebenfalls mit Polymer umgesetzt.

Die Shadow-DOM-API

Mit Shadow-DOM können Entwickler den Inhalt ihrer Komponente kapseln. In der gekapselten Komponente wirken weder die CSS-Regeln des umgebenden HTML-Dokuments, noch hat man von außen per DOM-API Zugriff auf diese Elemente. So einen Schutz vor äußeren Eingriffen erlaubt sonst nur das <iframe>-Element.

Das hat den Vorteil, dass Entwickler beim Erstellen der Komponente nicht mehr darauf achten müssen, dass die CSS-Klassen innerhalb der Komponente einzigartig genug sind, um nicht unbeabsichtigt äußere Elemente zu beeinflussen. Außerdem müssen sie sich keine Sorgen mehr darüber machen, dass sehr allgemein gehaltene CSS-Selektoren im umgebenden HTML-Dokument – wie „p { color: fuchsia; }“ – das Styling der Komponente durcheinander bringen.

Das <template>-Element

Das <template>-Element bringt nicht initial benötigten HTML-Code im Dokument unter, ohne dass der HTML-Parser diesen interpretiert. So werden beispielsweise enthaltene Bilder nicht geladen. Vergleichbar ist das mit dem bisher gängigen Workaround, bei dem Entwickler ein <script>-Element nutzen, dessen type-Attribut kein „text/javascript“ enthält. Das <template>-Element liefert nun eine standardisierte Lösung und eine spezielle API zum Auslesen des enthaltenen HTML-Codes.

Anzeige
Anzeige

HTML-Imports

HTML-Imports können komplette HTML-Dateien mit Hilfe des <link rel="import">-Elements laden. Enthaltenes JavaScript wird dann im globalen Kontext der Seite interpretiert, die den HTML-Import beherbergt. Dies ist nicht mit Includes zu verwechseln, wie man sie von Templating-Sprachen kennt. Vielmehr laden HTML-Imports HTML-Dateien in den aktuellen Kontext, so wie es mit CSS, JavaScript, Bildern und anderem schon länger möglich ist.

Das erste eigene Element

Die folgende Beispielanwendung definiert zum Einstieg ein <x-heart>-Element, das schlicht überall dort ein „<3“ anzeigt, wo es eingebunden ist. Der Bindestrich im Namen des Elements ist laut Spezifikation nötig, um Konflikte mit bestehenden und zukünftigen Standard-Elementen auszuschließen.

Die x-heart.html Datei
<template id="x-heart-template">
 <style>
 :host {
 display: inline-block;
 }
 span {
 color: red;
 padding: 0 .25rem;
 }
 </style>
 <span>&lt;3</span>
</template>

Listing 1

Dieser Code definiert das Template: Ein <span>-Element mit dem stilisierten Herz und ein bisschen CSS, um das Herz rot zu färben. Durch das Shadow-DOM können Entwickler hier unbesorgt den sehr allgemeinen span-Selektor nutzten. Der :host-Selektor bezieht sich übrigens auf das <x-heart>-Element selbst. Um das Element anzumelden, fügt man den folgenden <script>-Block in die Datei.

Anzeige
Anzeige
Element per Script-Block anmelden
<script>
 var XHeartProto = Object.create(HTMLElement.prototype);
 XHeartProto.createdCallback = function () {
 var template = document.getElementById('x-heart-template');
 var content = template.content.cloneNode(true);
 this.createShadowRoot();
 this.shadowRoot.appendChild(content);
 };
 document.registerElement('x-heart', {
 prototype: XHeartProto
 });
</script>

Listing 2

Dies erzeugt als erstes ein Objekt, das Eigenschaften vom HTMLElement-Objekt erbt. Dessen Methode createdCallback erzeugt das Shadow-DOM und befüllt es mit dem Inhalt des <template>-Elements. Abschließend meldet die document.registerElement-Methode das <x-heart>-Element an, sodass der Browser das <x-heart>-Element kennt. Mit einem HTML-Import lässt sich die Datei x-heart.html nun einbinden und das <x-heart>-Element nutzten:

Per HTML-Import das X-Heart-Element einbinden
<head>
 <script xsrc="webcomponents.js"></script>
 <link rel="import" href="x-heart.html">
</head>
<body>
 <x-heart></x-heart>
</body>

Listing 3

Obwohl dies ein sehr kleines Beispiel ist, fällt schon relativ viel Code an. Hätte das Element mehr Funktionalität, müsste man wesentlich mehr Eigenschaften und Methoden definieren. Kommt zudem eine individuelle Event-API dazu, wird der Script-Block noch komplexer. Dabei ist viel redundanter Code notwendig, der besser hinter einer vereinfachenden API-Schicht verborgen wäre.

Polymer fürs Wesentliche

Hier kommt Polymer ins Spiel. Das Projekt, das Google 2013 ins Leben rief, legt eine Abstraktionsschicht auf die Web-Components-APIs und ermöglicht dadurch einen deklarativeren Ansatz. Außerdem bietet es Templating und ein Two-way data binding, wie man es beispielsweise von Angular kennt. Darauf aufbauend gibt es eine Bibliothek mit bereits fertigen Elementen [3], die man für Web-Apps nutzen kann. Mit Polymer sähe das oben genannte Beispiel der Datei x-heart.html folgendermaßen aus:

Anzeige
Anzeige
X-Heart-Datei mit Polymer
<link rel="import" href="polymer.html">
<dom-module id="x-heart">
 <template>
 <!-- Das Template bleibt gleich! -->
 </template>
 <script>
 Polymer({
 is: 'x-heart'
 });
 </script>
</dom-module>

Listing 4

Am Anfang bindet der Code die Polymer-Bibliothek über einen HTML-Import ein. Diese führt das <dom-module>-Element ein, das das Beispiel-Element beschreibt. Dabei verändert sich das Template faktisch nicht. Auf der JavaScript-Seite hat Polymer jedoch schon einiges an Arbeit abgenommen. In einem weiteren Schritt lässt sich die Farbe des <x-heart>-Elements über ein color-Attribut konfigurieren, indem man das Template geringfügig anpasst:

Ein Color-Attribut einfügen
<template>
 <style>
 :host {
 display: inline-block;
 }
 span {
 padding: 0 .25rem;
 }
 </style>
 <span style$="color: {{color}}">&lt;3</span>
</template>

Listing 5

Nun fügt man ein style-Attribut in das <span>-Element ein, um die Farbe des Herzens aus den Eigenschaften des Elements auslesen zu können. Die Schreibweise style$="…" teilt Polymer mit, dass hier ein Data-Binding stattfindet. Außerdem muss man das Attribut innerhalb des Polymer-Objekts anmelden. Das sieht dann folgendermaßen aus:

Das Polymer-Objekt anmelden
<script>
 Polymer({
 is: 'x-heart',
 properties: {
 color: {
 type: String,
 value: 'red',
 reflectToAttribute: true
 }
 }
 });
</script>

Listing 6

Innerhalb der properties-Eigenschaft des Polymer-Objekts melden Entwickler die color-Eigenschaft an. Sie ist vom Typ „String“, der Default-Wert ist „red“. Der Befehl „reflectToAttribute: true“ sorgt dafür, dass sich Änderungen der Eigenschaft im gleichnamigen HTML-Attribut widerspiegeln. Die beiden folgenden Angaben bewirken daher dasselbe:

Anzeige
Anzeige
Die Farbe in Gelb ändern
document.querySelector('x-heart').color = 'yellow';
document.querySelector('x-heart').setAttribute('color', 'yellow');

Listing 7

Die Durchführung der Farbänderungen erledigt Polymer dank des Data-Bindings selbst. Damit das Herz auch noch schlägt, soll das <x-heart>-Element zusätzlich jede Sekunde einen pulse-Event aussenden, an den sich Callback-Funktionen binden lassen. Dies melden Entwickler ebenfalls im Polymer-Objekt an – und zwar innerhalb der created-Methode. Diese ist äquivalent zur nativen createdCallback-Methode und wird aufgerufen, wenn das Element erzeugt wird.

Einen Pulse-Event anlegen
Polymer({
 is: 'x-heart',
 ...,
 created: function () {
 setInterval(function () {
 this.fire('pulse');
 }.bind(this), 1000);
 }
});

Listing 8

An den pulse-Event des Elements können mit der addEventListener-Methode Callback-Funktionen gebunden werden, wie man es von klassischen DOM-Events kennt.

Eine Callback-Funktion anbinden
document.querySelector('x-heart').addEventListener('pulse', function () {
 // Mach etwas bei jedem Herzschlag ...
});

Listing 9

Alles ist ein Element!

Wie bereits erwähnt, bietet Polymer zusätzlich eine Bibliothek mit fertigen Elementen. Gemäß dem Paradigma „Alles ist ein Element!“ enthält diese jedoch nicht nur UI-Elemente wie Buttons, Dropdown-Menüs und ähnliches, sondern auch unsichtbare Elemente, die Entwickler über Attribute parametrisieren können, sodass sie zur programmatischen Nutzung während der Laufzeit der Web-Applikation zur Verfügung stehen.

Anzeige
Anzeige

Als Beispiel dient an dieser Stelle das Element <iron-ajax>. Dieses lässt sich im HTML-Code anlegen und konfigurieren. Anschließend kann es der Programmierer über seine DOM-API zum asynchronen Laden und Senden von Daten verwenden.

Ein Iron-Ajax-Element anlegen
<iron-ajax url="http://example.com/api/endpoint.json" handle-as="json"></iron-ajax>
<script>
 var ajaxElement = document.querySelector('iron-ajax');
 ajaxElement.addEventListener('response', function (event) {
 // Mach etwas mit dem `event.response`-Objekt ...
 });
 ajaxElement.generateRequest();
</script>

Listing 10

Dieses Beispiel zeigt nur ein Bruchteil dessen, was das <iron-ajax>-Element zu leisten vermag. Weitere Elemente ohne User-Interface bieten zum Beispiel Zugriff auf die Push-Messaging-API oder erleichtern das Anlegen eines Service Workers, um das Caching der Website zu optimieren.

Polymer im produktiven Einsatz

Noch sind die Web-Components-Spezifikationen nicht final und Änderungen an den APIs möglich. Polymer steht jedoch in einer stabilen Version 1.0 bereit. Auch ist der Browser-Support noch lückenhaft, sodass Interessierte um Polyfills nicht herumkommen. Entwickler müssen also mindestens die 39 KB große webcomponents-lite.js-Datei und die 118 KB große polymer.html-Datei in ihre Seite integrieren – das heißt sie müssen 160 KB Daten einbinden, bevor der Einsatz von Web Components überhaupt starten kann.

Für wen also Dateigröße und Evergreen-Browser-User kein Hindernis darstellen, kann Web Components einsetzen. Und wer sich schon mal in der Praxis anschauen will, wie Polymer funktioniert, wirft einen Blick auf die Website des Polymer-Projekts [4] oder geht im Github-Wiki auf der Seite des Polymer-Projekts eine lange Liste weiterer Praxisanwendungen [5] durch.

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
Kommentare

Community-Richtlinien

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Kommentar abgeben

Melde dich an, um Kommentare schreiben und mit anderen Leser:innen und unseren Autor:innen diskutieren zu können.

Anmelden und kommentieren

Du hast noch keinen t3n-Account? Hier registrieren

Anzeige
Anzeige