{"id":1380,"date":"2016-02-10T09:03:49","date_gmt":"2016-02-10T08:03:49","guid":{"rendered":"https:\/\/www.inovex.de\/\/?p=1380"},"modified":"2026-03-17T08:00:07","modified_gmt":"2026-03-17T07:00:07","slug":"webcomponents-tutorial","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/","title":{"rendered":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial]"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">In diesem Artikel wird von Grund auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird, welche Aufgaben durch Tools automatisiert werden k\u00f6nnen und welche Hilfsfunktionen Polymer bereitstellt, um die Webkomponente \u00fcbersichtlich zu strukturieren. Die Erstellung der Dokumentation, einer Livedemo und einiger Tests runden die Webkomponente ab. Abschlie\u00dfend wird die fertige Komponente auf den zwei popul\u00e4ren Verzeichnisseiten f\u00fcr Web Components ver\u00f6ffentlicht. Dieser Artikel bezieht sich auf Polymer in der Version 1.0. Ein weiterer Artikel wird sich mit dem \u00dcbergang von 0.5 auf 1.0 und die zuk\u00fcnftige Roadmap f\u00fcr Web Components besch\u00e4ftigen.<\/span><!--more--><\/p>\n<div style=\"background-color: #f4f4f4; padding: 1em;\">So wie in der Musik die Komposition die Zusammenstellung eines Musikst\u00fccks aus einzelnen, bereits vorhandenen Bestandteilen wie Noten und Melodien beschreibt, so wird auch bei Web Components die Verwendung vorhandener HTML-Elemente und weiterer Komponenten als Komposition bezeichnet. Ein Arrangement hingegen bezeichnet eine abgewandelte Version eines Musikst\u00fccks, das neue Gestaltungsmittel hinzuf\u00fcgt oder bestehende ver\u00e4ndert. Durch die Vererbungskonzepte, die Custom Elements mit sich bringen, k\u00f6nnte man im Falle der Web Components so auch von Arrangements der Elemente sprechen.<\/div>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Von-Action-Sheets-bis-WebComponents\" >Von Action Sheets bis WebComponents<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Historie-von-Web-Components\" >Historie von Web Components<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Vorbereitungen\" >Vorbereitungen<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#1-Erstellen-des-Grundgeruests\" >1. Erstellen des Grundger\u00fcsts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#2-Erstellen-der-Komponente\" >2. Erstellen der Komponente<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#3-Implementierung\" >3. Implementierung<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#4-Dokumentation-Tests-und-Demoseite\" >4. Dokumentation, Tests und Demoseite<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Migration-und-Veroeffentlichung-der-Komponente\" >Migration und Ver\u00f6ffentlichung der Komponente<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Verwendung-der-Komponente\" >Verwendung der Komponente<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Weitere-Ressourcen-und-%E2%80%9EBest-Practices%E2%80%9C\" >Weitere Ressourcen und \u201eBest Practices\u201c<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Fazit\" >Fazit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Weiterlesen\" >Weiterlesen<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#Were-hiring\" >We&#8217;re hiring!<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Von-Action-Sheets-bis-WebComponents\"><\/span>Von Action Sheets bis WebComponents<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Vor \u00fcber zwanzig Jahren entstand das Web zum Austausch von wissenschaftlichen Dokumenten. Erst durch die Entwicklung von JavaScript sind einfache, aber interaktive Webseiten und kleinere Webanwendungen m\u00f6glich geworden. Die Anforderungen haben sich seither drastisch ver\u00e4ndert, und Webanwendungen werden immer komplexer, aber es fehlt an standardisierten Strukturierungsm\u00f6glichkeiten auf Seiten des Frontends.<\/p>\n<p>Frameworks auf Server- und Clientseite k\u00f6nnen zwar bei der Strukturierung helfen, setzen aber in aller Regel auf propriet\u00e4re L\u00f6sungen \u2013 ein Standard fehlt. Dadurch ist es schwierig, verschiedene Frameworks parallel einzusetzen. Au\u00dferdem sind L\u00f6sungen nicht auf andere Projekte \u00fcbertragbar, da sie nicht kompatibel zueinander sind oder das Setup gro\u00dfe Schmerzen bereitet.<\/p>\n<div style=\"background-color: #f4f4f4; padding: 1em;\">\n<h2><span class=\"ez-toc-section\" id=\"Historie-von-Web-Components\"><\/span>Historie von Web Components<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Bereits seit 1998 wird versucht, dieses Problem der Webplattform zu l\u00f6sen, um Webanwendungen besser in Verhalten, Aussehen und Struktur zu gliedern. S\u00e4mtliche Versuche sind beim W3C eingereicht, haben es bislang aber nie zu einer Empfehlung geschafft.\u00a0Einen kleinen R\u00fcckblick auf die Jahre 1998 bis 2011 zeigt Abb. 1.<\/p>\n<figure id=\"attachment_1438\" aria-describedby=\"caption-attachment-1438\" style=\"width: 800px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/webcomponents-timeline.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-1438\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/webcomponents-timeline-1024x820.png\" alt=\"Timeline Web Components\" width=\"800\" height=\"641\" \/><\/a><figcaption id=\"caption-attachment-1438\" class=\"wp-caption-text\">Abb. 1: Historische Entwicklung von Spezifikationen zur besseren Strukturierung<\/figcaption><\/figure>\n<p><a href=\"http:\/\/www.w3.org\/TR\/NOTE-AS\" target=\"_blank\" rel=\"noopener\">Action Sheets<\/a> sind ein von Netscape im Jahre 1998 verfolgter Ansatz, zus\u00e4tzlich zur Trennung der Pr\u00e4sentation (CSS) und Struktur (HTML) auch das Verhalten (JavaScript) zu abstrahieren. Ein Action Sheet besitzt dieselbe Struktur wie auch Style Sheets, verkn\u00fcpft dabei aber Elemente mit JavaScript, anstatt mit Stileigenschaften. Als Attribut sind ausschlie\u00dflich die nativen Events (onclick, onfocus, &#8230;) erlaubt. Der Wert ist JavaScript-Code, der inline als String angegeben wird.<\/p>\n<p>Noch im selben Jahr versuchte Microsoft durch die <a href=\"http:\/\/www.w3.org\/TR\/NOTE-HTMLComponents\" target=\"_blank\" rel=\"noopener\">HTML Components (HTC)<\/a> einen Ansatz \u00fcber XML. Anders als bei Action Sheets kann das Verhalten von Standard-HTML-Elementen \u00fcberschrieben oder erweitert werden. Dar\u00fcber hinaus k\u00f6nnen neue Attribute und Methoden auf den Elementen hinzugef\u00fcgt werden. Die Definition einer Komponente erfolgt in einer XML-Datei mit der Dateiendung .htc. Als neues CSS-Attribut wird behaviour eingef\u00fchrt, das als Wert url(..\/file.htc) besitzt. Eine der bekanntesten Komponenten d\u00fcrfte <a href=\"http:\/\/css3pie.com\/\" target=\"_blank\" rel=\"noopener\">CSS3 PIE<\/a> sein, das fehlende CSS3-Unterst\u00fctzung im Internet Explorer nachr\u00fcstet. HTC war bis einschlie\u00dflich Version 9 des Internet Explorers integriert.<\/p>\n<p>Auch der Versuch, die beiden Ans\u00e4tze 1999 miteinander in BECSS (Behavioral Extensions to CSS) zu vereinen, scheiterte aufgrund fehlenden Interesses an der Implementierung einer komplexen <a href=\"http:\/\/www.w3.org\/TR\/becss\/\" target=\"_blank\" rel=\"noopener\">Binding-Sprache<\/a>, die hierf\u00fcr zwingend erforderlich ist.<\/p>\n<p>Im Jahr 2000 startete Mozilla dann die Entwicklung an <a href=\"http:\/\/www.w3.org\/TR\/xbl\/\" target=\"_blank\" rel=\"noopener\">XBL (XML Binding Language)<\/a>, die durch HTC beeinflusst worden ist und selbst wiederum BECSS beeinflusst hat. Die Entwicklung ist 2006 in einer nahezu vollst\u00e4ndigen Neuentwicklung als XBL 2.0 weiterverfolgt worden und die Entwicklungen an Version 1 stoppten.<\/p>\n<p>Im Gegensatz zu BECSS f\u00fchrte XBL 2.0 auch Templates ein, die es erlauben, in bestehende Elemente im Webdokument Knoten einzuf\u00fcgen, die zwar im Renderingprozess ber\u00fccksichtigt, nicht aber in das Document Object Model des Webdokuments eingef\u00fcgt werden. In der Spezifikation ist neben Templates bereits die Rede von Shadow-Trees, Event Retargeting und Custom-Setters\/Getters, die sp\u00e4ter unter dem Namen Web Components in HTML-Templates (zum HTML5-Standard geh\u00f6rend), Shadow DOM und Custom Elements zu gro\u00dfen Teilen \u00fcbernommen wurden. XBL 2.0 war eine zu komplexe Spezifikation, die versuchte, zu viele Use Cases abzudecken, weshalb sie letztendlich seitens des Google-Chrome-Teams <a href=\"https:\/\/lists.w3.org\/Archives\/Public\/public-webapps\/2011JulSep\/1568.html\" target=\"_blank\" rel=\"noopener\">nicht weiter verfolgt<\/a> wurde.<\/p>\n<p>Ende 2011 verfasste schlie\u00dflich Dimitri Glazkov (Google) zusammen mit anderen Use Cases und erarbeitete mit Hayato Ito (Google) und Hajime Morrita (Google) die <a href=\"https:\/\/wiki.whatwg.org\/wiki\/Component_Model\" target=\"_blank\" rel=\"noopener\">Spezifikationen<\/a>. Durch die Implementierung des parallel dazu entwickelten Polyfills <em>webcomponents.js<\/em>, der Bibliothek Polymer und durch eine mittlerweile stark gewachsene Community entstand so eine solide und gut unterst\u00fctzte Basis, um Web Components bereits heute auf allen relevanten, modernen Browsern \u2013 insbesondere auf mobilen Ger\u00e4ten \u2013 einzusetzen.<\/p>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"Vorbereitungen\"><\/span>Vorbereitungen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>F\u00fcr einen ersten und einfachen Einstieg in Polymer bietet es sich an, den zur Verf\u00fcgung stehenden <a href=\"https:\/\/github.com\/yeoman\/generator-polymer\" target=\"_blank\" rel=\"noopener\">Polymer-Generator<\/a> zu verwenden, um die grundlegende App-Struktur in einem \u201eBest-Practice-Ansatz\u201c vollautomatisch erzeugen zu lassen. Bevor es nun losgeht, muss zun\u00e4chst <a href=\"http:\/\/www.nodejs.org\/\" target=\"_blank\" rel=\"noopener\">Node.js<\/a> installiert sein. Anschlie\u00dfend k\u00f6nnen \u00fcber die Kommandozeile auch dessen Paketmanager npm genutzt und dar\u00fcber die weiteren Tools Yeoman (Scaffolder) und der Polymer-Generator installiert werden:<\/p>\n<pre class=\"lang:sh decode:true \">npm install -g yo@1.4.8 &amp;&amp; npm install -g generator-polymer@1.2.1<\/pre>\n<p>Bower (Dependency-Manager) und gulp\/Grunt (Taskrunner) werden hier nicht explizit installiert, da dies sp\u00e4ter vom Generator \u00fcbernommen wird.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"1-Erstellen-des-Grundgeruests\"><\/span>1. Erstellen des Grundger\u00fcsts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Prinzipiell bietet der Generator zwei Wege, um eine neue Komponente zu erstellen:<\/p>\n<ul>\n<li>Erstellung einer wiederverwendbaren Komponente, die mit anderen geteilt werden soll.<\/li>\n<li>Erstellung einer Komponente, die nur innerhalb eines Projekts genutzt werden soll.<\/li>\n<\/ul>\n<p>F\u00fcr die umzusetzende Komponente w\u00e4re der erste Weg sicherlich der richtige, allerdings ist es einfacher, zun\u00e4chst eine simple App durch den Generator erstellen zu lassen. Die Migration in eine Standalone-Komponente wird sp\u00e4ter in diesem Artikel erkl\u00e4rt.<\/p>\n<p>Folgender Befehl erstellt ein vollst\u00e4ndiges Polymer-Projekt mit entsprechendem Boilerplate-Code und einigen beispielhaft implementierten Komponenten:<\/p>\n<pre class=\"lang:sh decode:true \">mkdir tiny-polyblog &amp;&amp; cd tiny-polyblog &amp;&amp; yo polymer:app<\/pre>\n<p>Bei den R\u00fcckfragen werden der web-component-tester und die Dokumentation ausgew\u00e4hlt.<\/p>\n<p>gulp, welches als Build-Tool mitinstalliert wird, ist bereits vollst\u00e4ndig vorkonfiguriert und integriert neben einem Webserver auch so genannte File Watchers, die den Browser beim \u00c4ndern von Dateien zum Neuladen der Seite veranlassen. Zus\u00e4tzlich sind die folgenden Funktionen integriert:<\/p>\n<ul>\n<li>CSS-Autoprefixer, um pr\u00e4fixfreies CSS schreiben zu k\u00f6nnen<\/li>\n<li>CSS-\/JS-\/HTML-\/Bild-Minifizierer zur Reduzierung der Dateigr\u00f6\u00dfen<\/li>\n<li>Polymer Vulcanizer zur Konkatenation von HTML-Imports in eine einzige Datei<\/li>\n<\/ul>\n<p>Damit ist eine solide Out-of-the-box-L\u00f6sung verf\u00fcgbar, mit der direkt gearbeitet werden kann. Die Ordnerstruktur enth\u00e4lt neben den Konfigurationsdateien und 3rd-Party-Komponenten\/-tools die eigentliche Anwendung im Ordner <em>app<\/em>.<\/p>\n<p>Das Starten des Webservers erfolgt auf der Konsole mit gulp serve. Der Browser sollte daraufhin ge\u00f6ffnet werden und zeigt die Beispielwebapplikation. W\u00fcrde die Webapplikation deployt werden, so wird durch den Befehl <em>gulp serve:dist<\/em> die Anwendung nach oben genannten Optimierungen im Ausgabeordner dist erzeugt.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"2-Erstellen-der-Komponente\"><\/span>2. Erstellen der Komponente<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Als praktisches Beispiel soll eine Komponente erstellt werden, die aus einem JSON-, RSS- oder XML-Dokument eine Listendarstellung mit Titel, Datum, Kategorie, Inhalt und einem Vorschaubild erzeugt. Durch weitere Attribute soll zwischen zwei unterschiedlichen Ansichten umgeschaltet und eine Sortierung der Daten nach Datum auf- oder absteigend m\u00f6glich sein.<\/p>\n<p>Die Komponente kann \u00fcber die Konsole im Ordner tiny-polyblog mit folgendem Befehl durch Yeoman erstellt werden:<\/p>\n<pre class=\"lang:sh decode:true \">yo polymer:el ph-listview iron-ajax iron-image iron-list --docs<\/pre>\n<p>Die Nachfrage, ob ein Import in der Datei app\/elements\/elements.html hinzugef\u00fcgt werden soll, kann mit Y bzw. y bejaht werden. Der Yeoman-Generator erzeugt daraufhin die Dateien <em>demo\/index.html<\/em>, <em>index.html<\/em>, <em>ph-listview.html<\/em> im Ordner <em>app\/elements\/ph-listview\/<\/em>. Da die Iron-Elemente ajax, image und list sp\u00e4ter noch ben\u00f6tigt werden, werden sie direkt in diesem Befehl mit angegeben.<\/p>\n<p>Die Demo- und Indexseiten werden aufgrund des Flags &#8211;docs hinzugef\u00fcgt. Eine Demoseite wird normalerweise nur f\u00fcr eigenst\u00e4ndige Komponenten erstellt. Es ist aber durchaus sinnvoll, diese auch f\u00fcr Komponenten einzusetzen, die nur innerhalb eines Projekts verwendet werden, wenn beispielsweise mehrere Entwickler an dem Projekt gemeinsam arbeiten. Au\u00dferdem sollten diese Dateien f\u00fcr eine eigenst\u00e4ndige Komponente sowieso immer vorhanden sein.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"3-Implementierung\"><\/span>3. Implementierung<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Mit der Komponente sind asynchrone Requests m\u00f6glich, ohne dabei auch nur eine Zeile JavaScript-Code schreiben zu m\u00fcssen. Konfiguriert werden die Attribute per Data Binding. F\u00fcr die beiden Darstellungsformen der Liste k\u00f6nnen bedingte, verschachtelte Templates genutzt werden, die je nach gesetztem Attributwert das entsprechende Template instanziieren. Hierdurch ergibt sich die in Listing 1 gezeigte, vereinfachte Struktur des HTML-Markups.<\/p>\n<pre class=\"lang:xhtml decode:true \" title=\"Listing 1\">&lt;link rel=\"import\" href=\"...\"&gt;\r\n\r\n&lt;dom-module id=\"ph-listview\"&gt;\r\n\r\n    &lt;template&gt;\r\n\r\n        &lt;iron-ajax\r\n\r\n            auto\r\n\r\n            url=\"{{feed}}\"\r\n\r\n            on-response=\"{{_requestCompleted}}\"&gt;\r\n\r\n        &lt;\/iron-ajax&gt;\r\n\r\n        &lt;template\r\n\r\n            is=\"dom-if\" if=\"{{_isDefault(_entries, viewType)}}\"&gt;\r\n\r\n            &lt;!-- ... --&gt;\r\n\r\n        &lt;\/template&gt;\r\n\r\n        &lt;template is=\"dom-if\" if=\"{{_isCompact(_entries, viewType)}}\"&gt;\r\n\r\n        &lt;!-- ... --&gt;\r\n\r\n        &lt;\/template&gt;\r\n\r\n    &lt;\/template&gt;\r\n\r\n    &lt;script&gt;\r\n\r\n    \/\/ ...\r\n\r\n    &lt;\/script&gt;\r\n\r\n&lt;\/dom-modue&gt;<\/pre>\n<p>Die in den doppelt geschweiften Klammern stehenden Variablennamen werden durch das Data Binding mit den entsprechenden Variablennamen aus dem JavaScript-Kontext gebunden. Die beiden Ansichten werden so durch viewType entsprechend beeinflusst. Die Instanziierung des entsprechenden Templates \u00fcbernimmt Polymer.<\/p>\n<p>Die Komponente wird zwar deklarativ genutzt, ist aber nicht sichtbar. Sie liefert ausschlie\u00dflich funktionale Aspekte. Als Attribut url wird ein URL durch das \u00f6ffentliche Attribut feed gebunden, auf der ein einfacher GET-Request ausgef\u00fchrt wird. Sobald die Antwort vom Server erhalten ist, wird durch den deklarativen Polymer-Callback-Handler on-response ein Event gefeuert, das von der Methode _requestCompleted behandelt wird. Per Konvention beginnen private Methoden und Attribute mit einem Unterstrich.<\/p>\n<p>Der Skriptanteil besteht im Wesentlichen aus der Definition der \u00f6ffentlichen Attribute der Komponente , sodass diese auch von einem Verbraucher entsprechend konfiguriert werden k\u00f6nnen. Ben\u00f6tigt werden dabei die folgenden Attribute:<\/p>\n<ul>\n<li>feed: der URL, der als Datenquelle genutzt werden soll (HTTP-Ressource)<\/li>\n<li>handle-as: der Typ der Datenquelle (json, rss oder xml)<\/li>\n<li>view-type: die gew\u00fcnschte Ansicht (default oder compact)<\/li>\n<li>sort-by-date-asc: aufsteigende Sortierung der Eintr\u00e4ge (true oder false)<\/li>\n<li>date-format: ein f\u00fcr Moment.js valides Datumsformat, mit dem die Zeit geparst und anschlie\u00dfend sortiert wird<\/li>\n<\/ul>\n<p>Diese Attribute werden mit ihren Default-Werten, wie in Listing 2 zu sehen, definiert. Die Bindestrich-Notation der Attribute wird f\u00fcr den Javascript-Anteil automatisch auf die entsprechende Darstellung in Camelcase gemappt (z.B. wird handle-as automatisch zu handleAs).<\/p>\n<pre class=\"lang:xhtml decode:true\" title=\"Listing 2\">&lt;dom-module id=\"ph-listview\"&gt;\r\n\r\n    &lt;template&gt;\r\n\r\n        &lt;!-- (analog zu Listing 1) --&gt;\r\n\r\n    &lt;\/template&gt;\r\n\r\n    &lt;script&gt;\r\n\r\n        Polymer({\r\n\r\n            is: 'ph-listview',\r\n\r\n            properties: {\r\n\r\n               \/\/ ...\r\n\r\n               viewType: {\r\n\r\n                    type: String,\r\n\r\n                    value: 'default',\r\n\r\n                    reflect: true \/\/ reflektiert Attributswert\u00e4nderungen innerhalb\r\n\r\n               }, \/\/ der Komponente auch in den DOM\r\n\r\n               \/\/ ...\r\n\r\n            }\r\n\r\n            \/\/ ...\r\n\r\n        });\r\n\r\n    &lt;\/script&gt;\r\n\r\n&lt;\/dom-module&gt;<\/pre>\n<p>Durch die Komponente verursachte \u00c4nderungen dieser Attribute werden per Default nicht in den DOM geschrieben. Diese Reflektion ist auch nur dann sinnvoll, wenn die Au\u00dfenwelt auf \u00c4nderungen reagieren soll. In Listing 2 wird einzig viewType auf den Wert default gesetzt, wenn kein Wert angegeben ist.<\/p>\n<p>Zur Darstellung beliebiger Datenformate kann eine Funktion zum Parsen der Daten \u00fcbergeben werden. Der R\u00fcckgabewert muss dabei ein Array in folgendem Format sein:<\/p>\n<pre class=\"lang:js decode:true \">[{\r\n\r\ntitle: 'My Title',\r\n\r\ndate: '2010-01-01T05:06:07',\r\n\r\ncategory: 'My Category',\r\n\r\ndescription: 'A bit more text',\r\n\r\nlink: 'http:\/\/www.google.com\/'\r\n\r\n}]<\/pre>\n<p>Entsprechend den enthaltenen Attributen wird daraus eine Liste erzeugt. Bevor dies aber soweit ist, muss zun\u00e4chst die JavaScript-Implementierung umgesetzt werden (Listing 3). Als Einstiegspunkt in die Komponente werden dabei zun\u00e4chst alle internen Variablen initialisiert. Dies geschieht durch die Lifecycle-Callbacks. Einer davon ist <em>created<\/em>. Dieser wird als erster aller Lifecycle-Callbacks ausgef\u00fchrt. Weitere finden sich im <a href=\"https:\/\/www.polymer-project.org\/1.0\/docs\/devguide\/feature-overview.html\" target=\"_blank\" rel=\"noopener\">Developer Guide<\/a>.<\/p>\n<pre class=\"lang:js decode:true\" title=\"Listing 3\">&lt;dom-module is=\"ph-listview\"&gt;\r\n\r\n    &lt;template&gt;\r\n\r\n        &lt;!-- (analog zu Listing 1) --&gt;\r\n\r\n    &lt;\/template&gt;\r\n\r\n    &lt;script&gt;\r\n\r\n        Polymer({\r\n\r\n            is: 'ph-listview',\r\n\r\n            properties: {\r\n\r\n                feed: {\r\n\r\n                type: String,\r\n\r\n                value: '',\r\n\r\n                observer: '_feedChanged'\r\n\r\n                },\r\n\r\n            \/\/ ...\r\n\r\n            },\r\n\r\n            setResponseParseFunc: function(func) {\r\n\r\n                this._responseParseFunc = func;\r\n\r\n            },\r\n\r\n            created: function() {\r\n\r\n                this._responseParseFunc = null; \/\/ response parse function\r\n\r\n                this._sortAsc = false; \/\/ the sort order\r\n\r\n                this._entries = []; \/\/ holds the parsed response data\r\n\r\n            },\r\n\r\n            _feedChanged: function(oldVal, newVal) {\r\n\r\n                if (newVal) {\r\n\r\n                    \/\/ call url and fetch feed\r\n\r\n                }\r\n\r\n            },\r\n\r\n        \/\/ ...\r\n\r\n        });\r\n\r\n    &lt;\/script&gt;\r\n\r\n&lt;\/dom-module&gt;<\/pre>\n<p>Listing 3 enth\u00e4lt die \u00f6ffentliche Methode setResponseParseFunc, den Callback created sowie die Definition f\u00fcr das feed-Attribut, das eine Observer-Eigenschaft spezifiziert, das \u00c4nderungen der Attribute entsprechend auf die gezeigten Methoden mappt. Es fehlt jetzt nur noch die Implementierung des Callback-Handlers der -Komponente, die die Antwort des Requests an die vom Verbraucher \u00fcbergebene Funktion \u00fcbergibt und das Ergebnis in <em>_entries<\/em> speichert. Bei RSS-Feeds wird keine Parse-Funktion ben\u00f6tigt.<\/p>\n<p>Der \u00dcbersichtlichkeit halber wird die RSS-Parse-Funktion als Behavior ausgelagert. Behaviors sind simple JavaScript-Objekte, die gemeinsam verwendete Funktionalit\u00e4t separieren und so in verschiedenen Komponenten eingesetzt werden k\u00f6nnen.<\/p>\n<p>Listing 4 zeigt den Import der Behavior, die in einer HTML-Datei als Skript eingebunden ist und die private, statische Funktion _handleResponseStatic, die in einer selbstausf\u00fchrenden, anonymen Funktion gekapselt ist. Sie sch\u00fctzt an dieser Stelle vor allem vor dem unbefugten Zugriff der \u201eAu\u00dfenwelt\u201c auf die dort definierten Variablen. Gleichzeitig bleiben dadurch die Instanzen der Komponente leichtgewichtiger. Die bislang erw\u00e4hnten Elemente werden im <a href=\"https:\/\/www.polymer-project.org\/1.0\/docs\/devguide\/feature-overview.html\" target=\"_blank\" rel=\"noopener\">Polymer API Developer Guide<\/a> vorgestellt.<\/p>\n<pre class=\"lang:js decode:true\" title=\"Listing 4\">&lt;link rel=\"import\" href=\"..\/helpers.html\"&gt;\r\n\r\n&lt;dom-module id=\"ph-listview\"&gt;\r\n\r\n    &lt;template&gt;\r\n\r\n        &lt;!-- (analog zu Listing 1) --&gt;\r\n\r\n    &lt;\/template&gt;\r\n\r\n    &lt;script&gt;\r\n\r\n        (function() {\r\n\r\n            \/\/ private static in IIFE\r\n\r\n            var _handleResponseStatic = function(handleAs, detail) {\r\n\r\n                \/\/ ...\r\n\r\n                return response;\r\n\r\n            };\r\n\r\n            Polymer({\r\n\r\n                \/\/ ... (analog zu Listing 3) ...\r\n\r\n                _requestCompleted: function(event) {\r\n\r\n                    if (event.detail.status != 200) { console.warn('...'); return; }\r\n\r\n                    var response = _handleResponseStatic(this.handleAs, event.detail.response);\r\n\r\n                    this._entries = this._responseParseFunc(response);\r\n\r\n                    \/\/ ...\r\n\r\n                 }\r\n\r\n             },\r\n\r\n             behaviors: [Polymer.MyHelper],\r\n\r\n             \/\/ ...\r\n\r\n             });\r\n\r\n        })();\r\n\r\n    &lt;\/script&gt;\r\n\r\n&lt;\/dom-module&gt;<\/pre>\n<p>Die Behavior wird ganz einfach als einziges Element eines Arrays in der Eigenschaft behaviors \u00fcbergeben. Der Polymer-Helper kopiert die in MyHelper enthaltenen Objekte zur Laufzeit in die Komponente und erlaubt dadurch die Verwendung der dortigen Funktionen. Sofern unterschiedliche Namen f\u00fcr Variablen und Methoden definiert werden, treten dabei keine Probleme auf.<\/p>\n<p>In Listing 5 ist ein Ausschnitt f\u00fcr die Default-Ansicht des Templates angegeben, das durch die Verwendung von eine performante Endlosliste generiert und mithilfe von ein cropping des Bilds erreicht wird. Zus\u00e4tzlich werden Computed Bindings eingesetzt, um die Listendarstellung zu sortieren und das Datum zu formatieren, ohne dabei das Array _entries zu ver\u00e4ndern.<\/p>\n<pre class=\"lang:js decode:true\" title=\"Listing 5\">&lt;dom-module id=\"ph-listview\"&gt;\r\n\r\n&lt;template&gt;\r\n\r\n    &lt;!-- (analog zu Listing 1) --&gt;\r\n\r\n    &lt;iron-list data=\"{{_filterSortEntries(_entries)}}\"&gt;\r\n\r\n        &lt;template&gt;\r\n\r\n            &lt;!-- ... --&gt;\r\n\r\n            &lt;iron-image src=\"{{ model.thumb }}\" sizing=\"contain\"&gt;&lt;\/iron-image&gt;\r\n\r\n            &lt;!-- ... --&gt;\r\n\r\n            &lt;div class=\"title\"&gt;{{ model.title }}&lt;\/div&gt;\r\n\r\n            &lt;div class=\"subtitle\"&gt;\r\n\r\n                &lt;span class=\"date\"&gt;{{_filterDateView(model.date)}}&lt;\/span&gt;,\r\n\r\n                &lt;span class=\"category\"&gt;{{ model.category }}&lt;\/span&gt;\r\n\r\n            &lt;\/div&gt;\r\n\r\n            &lt;!-- ... --&gt;\r\n\r\n        &lt;\/template&gt;\r\n\r\n    &lt;\/iron-list&gt;\r\n\r\n&lt;\/template&gt;\r\n\r\n&lt;!-- ... --&gt;\r\n\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\n\r\n    \/\/ ... (analog zu Listing 4) ...\r\n\r\n&lt;\/script&gt;\r\n\r\n&lt;\/dom-module&gt;<\/pre>\n<p>So lassen sich sehr einfach einzelne Sichten erstellen und durch Komposition die Vorteile bereits vorhandener Funktionalit\u00e4t nutzen. Durch die Mischung imperativer und deklarativer Anteile entsteht eine bessere \u00dcbersicht, und gr\u00f6\u00dfere Funktionalit\u00e4ten lassen sich auf weitere Komponenten aufteilen oder in Behaviors auslagern. Der gesamte Quellcode findet sich <a href=\"https:\/\/github.com\/silentHoo\/ph-listview\" target=\"_blank\" rel=\"noopener\">im Repository<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"4-Dokumentation-Tests-und-Demoseite\"><\/span>4. Dokumentation, Tests und Demoseite<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Die Dokumentation kann direkt in Markdown-Syntax und JSDoc-Style in ph-listview.html erfolgen. Ruft man die generierte index.html \u00fcber einen Browser auf, so werden die Kommentare zu Methoden, Attributen, Events und die in der bower.json angegebene Versionsnummer sauber und ordentlich aufbereitet.<\/p>\n<p>F\u00fcr die Demoseite empfiehlt es sich, mehrere aussagekr\u00e4ftige Parameterkombinationen zu zeigen und auch zu dokumentieren, um anderen m\u00f6glichst viele M\u00f6glichkeiten der Komponente zu demonstrieren. Tests lassen sich ohne gro\u00dfen Aufwand direkt durch den Aufruf von <em>test\/ph-listview-basic.html<\/em> oder durch <em>gulp:test:local<\/em> durchf\u00fchren. Die Dokumentation, Tests und die Demoseite sind aus Platzgr\u00fcnden <a href=\"https:\/\/github.com\/silentHoo\/ph-listview\" target=\"_blank\" rel=\"noopener\">im Repository angegeben<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Migration-und-Veroeffentlichung-der-Komponente\"><\/span>Migration und Ver\u00f6ffentlichung der Komponente<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Die Migration der Komponente in eine eigenst\u00e4ndige Komponente ist einfach und besteht im Wesentlichen aus dem in Abbildung 2 beschriebenen Ablauf.<\/p>\n<figure id=\"attachment_1389\" aria-describedby=\"caption-attachment-1389\" style=\"width: 750px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-1389\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-750x1024.png\" alt=\"Ver\u00f6ffentlichungsprozess\" width=\"750\" height=\"1024\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-750x1024.png 750w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-220x300.png 220w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-768x1048.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-1126x1536.png 1126w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-1501x2048.png 1501w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-1920x2620.png 1920w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-400x546.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/veroeffentlichungsprozess-360x491.png 360w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><figcaption id=\"caption-attachment-1389\" class=\"wp-caption-text\">Abb. 2: Ver\u00f6ffentlichungsprozess einer neuen, eigenen Komponente<\/figcaption><\/figure>\n<p>In einem neuen Verzeichnis k\u00f6nnen folgende Befehle ausgef\u00fchrt werden:<\/p>\n<pre class=\"lang:sh decode:true \">yo polymer:seed ph-listview\r\n\r\ncd ph-listview\r\n\r\nbower install PolymerElements\/iron-elements#^1.0.0 moment --save\r\n\r\nbower install PolymerElements\/paper-elements#^1.0.0 --save-dev<\/pre>\n<p>Dies erzeugt das Skelett der Komponente und f\u00fcgt alle ben\u00f6tigten Abh\u00e4ngigkeiten hinzu. Da die Radio-Buttons, die zu den Paper-Elementen geh\u00f6ren, nur in der Demo verwendet werden, k\u00f6nnen sie als dev-dependencies angegeben werden. Durch das simple Kopieren der CSS-\/HTML-Inhalte und der Demo, sowie der Anpassung der HTML-Import-Pfade, der Keywords und Version der bower.json, ist die Komponente bereit zur Ver\u00f6ffentlichung. Damit die Doku und Demo auch direkt auf dem statischen Webserver github.io landen und damit auch ohne eigenen Webserver abrufbar sind, wird der Befehl<\/p>\n<pre class=\"lang:sh decode:true \">yo polymer:gh<\/pre>\n<p>im Verzeichnis ph-listview ausgef\u00fchrt. Dieser erzeugt den Git-Branch gh-pages, l\u00f6st alle Abh\u00e4ngigkeiten auf und pusht den gesamten Inhalt auf GitHub. Erreichbar ist die Komponente dann unter http:\/\/.github.io\/ph-listview.<\/p>\n<p>Damit die Komponente auch auf den gr\u00f6\u00dften Web-Component-Verzeichnisseiten CustomElements.io und Component.kitchen gelistet wird, muss der Master-Branch mit einem <a href=\"http:\/\/semver.org\/\" target=\"_blank\" rel=\"noopener\">Semver-Tag<\/a> versehen werden und anschlie\u00dfend der Bower-Registry hinzugef\u00fcgt werden:<\/p>\n<pre class=\"lang:sh decode:true \">bower register ph-listview git:\/\/github.com\/&lt;user&gt;\/ph-listview.git<\/pre>\n<p>Nun ist alles geschafft und die Komponente in wenigen Tagen auf den Seiten auffindbar.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Verwendung-der-Komponente\"><\/span>Verwendung der Komponente<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Die Komponente l\u00e4sst sich nach der Installation \u00fcber Bower in jedem beliebigen Projekt verwenden:<\/p>\n<pre class=\"lang:sh decode:true \">bower register ph-listview git:\/\/github.com\/&lt;user&gt;\/ph-listview.git<\/pre>\n<p>Der ben\u00f6tigte HTML-Code ist simpel:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;link rel=\"import\" href=\"..\/bower_components\/ph-listview\/ph-listview.html\"&gt;\r\n\r\n&lt;ph-listview\r\n\r\n    feed=\"http:\/\/&lt;url-zum-rss-feed&gt;\/feed.rss\"\r\n\r\n    handle-as=\"rss\"&gt;\r\n\r\n&lt;\/ph-listview&gt;<\/pre>\n<p>F\u00fcr weitere Codebeispiele sei an dieser Stelle auf die <a href=\"https:\/\/github.com\/silentHoo\/ph-listview\" target=\"_blank\" rel=\"noopener\">Livedemo<\/a> verwiesen.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Weitere-Ressourcen-und-%E2%80%9EBest-Practices%E2%80%9C\"><\/span>Weitere Ressourcen und \u201eBest Practices\u201c<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Neben dem <a href=\"https:\/\/www.polymer-project.org\/1.0\/docs\/devguide\/feature-overview.html\" target=\"_blank\" rel=\"noopener\">offiziellen API Developer Guide zu Polymer<\/a> wird seit M\u00e4rz 2015 auch eine Art Checkliste vorangetrieben, die bew\u00e4hrte \u201eBest Practices\u201c f\u00fcr die Erstellung von Komponenten <a href=\"https:\/\/github.com\/webcomponents\/gold-standard\/wiki\" target=\"_blank\" rel=\"noopener\">in einem Wiki<\/a> festzuhalten versucht. Ein \u00e4hnlicher Ansatz findet sich ebenfalls auf github.com, bei dem bew\u00e4hrte Polymer-Patterns durch Beispiel-Snippets gezeigt werden. Unter der Endung <em>\/PolymerLabs\/polymer-patterns<\/em> ist dieser nachzuvollziehen. Das sind gute Referenzen, die bei der Erstellung eigener Komponenten genutzt werden sollten. Auch der Blick in die Paper- und Core-Elemente ist zu empfehlen.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Fazit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Durch die zur Verf\u00fcgung stehenden Generatoren f\u00fcr Polymer ist ein sehr einfacher Einstieg in die Welt der Web Components m\u00f6glich. Der Polymer API Developer Guide gibt durch praktische Beispiele einen schnellen \u00dcberblick \u00fcber die zur Verf\u00fcgung stehenden Funktionen und M\u00f6glichkeiten von Polymer.<\/p>\n<p>Die Ver\u00f6ffentlichung einer Komponente ist mit geringem Aufwand sehr einfach durchzuf\u00fchren. Dank GitHub ist kein eigener Webserver notwendig, um eine Demo- und Dokuseite f\u00fcr die ver\u00f6ffentlichte Komponente bereitzustellen. Weitere Vorteile ergeben sich durch die Nutzung der Bower-Registry, bei der eigene Komponenten registriert werden k\u00f6nnen und so die Komponente auch auf den beiden popul\u00e4ren Galeriewebseiten <em>CustomElements.io<\/em> und <em>Component.kitchen<\/em> erscheint.<\/p>\n<p>Das Tooling, die Polyfills und Polymer werden dabei von erfahrenen Entwicklern und einer sehr gro\u00dfen Community entwickelt, einige davon arbeiten direkt bei Google. Durch diese Art der engen Zusammenarbeit zwischen Webentwicklern, Core-Entwicklern des Chrome-Teams und Spezifikationsschreibenden entsteht ein Dialog, der in der Vergangenheit bei Webstandards selten zu sehen war.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Weiterlesen\"><\/span>Weiterlesen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Mehr Informationen zu unseren Dienstleistungen rund um die Web-Entwicklung gibt es <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/mobile-web\/\" target=\"_blank\" rel=\"noopener\">auf unserer Website<\/a>. Unser Portfolio umfasst au\u00dferdem die <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/app-entwicklung\/\" target=\"_blank\" rel=\"noopener\">Anwendungsentwicklung f\u00fcr Android &amp; iOS<\/a> mit speziellem Fokus auf <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/mobile-enterprise\/\" target=\"_blank\" rel=\"noopener\">Enterprise-Apps<\/a>. F\u00fcr direkten Kontakt schreibt an <a href=\"mailto:info@inovex.de\" target=\"_blank\" rel=\"noopener\">info@inovex.de<\/a> oder ruft an unter <a href=\"tel:+497216190210\" target=\"_blank\" rel=\"noopener\">+49 721 619 021-0<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Were-hiring\"><\/span>We&#8217;re hiring!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Tapetenwechsel gef\u00e4llig? Wir sind auf der Suche nach begeisterten Frontend-Entwicklern, die unsere Projektteams im Umfeld von JavaScript, HTML und CSS unterst\u00fctzen und auch vor innovativen Themen wie AngularJS und Progressive Web Apps nicht zur\u00fcckschrecken. <strong>Jetzt Bewerben!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Artikel wird von Grund auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird, welche Aufgaben durch Tools automatisiert werden k\u00f6nnen und welche Hilfsfunktionen Polymer bereitstellt, um die Webkomponente \u00fcbersichtlich zu strukturieren. Die Erstellung der Dokumentation, einer Livedemo und einiger Tests runden die Webkomponente ab. Abschlie\u00dfend wird die fertige Komponente auf den zwei [&hellip;]<\/p>\n","protected":false},"author":77,"featured_media":1387,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[70],"service":[444],"coauthors":[{"id":77,"display_name":"Patrick Hillert","user_nicename":"phillert"},{"id":38,"display_name":"Johannes Reuter","user_nicename":"jreuter"}],"class_list":["post-1380","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-web","service-frontend"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2016-02-10T08:03:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-17T07:00:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2300\" \/>\n\t<meta property=\"og:image:height\" content=\"678\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Patrick Hillert, Johannes Reuter\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents-1024x302.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@silentHoo\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Patrick Hillert\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"16\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Patrick Hillert, Johannes Reuter\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/\"},\"author\":{\"name\":\"Patrick Hillert\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/b2a8264915f219e25944c259e182a67f\"},\"headline\":\"Web Components selbst erstellen mit Polymer 1.0 [Tutorial]\",\"datePublished\":\"2016-02-10T08:03:49+00:00\",\"dateModified\":\"2026-03-17T07:00:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/\"},\"wordCount\":2751,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/artikelbild-webcomponents.jpg\",\"keywords\":[\"Web\"],\"articleSection\":[\"Applications\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/\",\"name\":\"Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/artikelbild-webcomponents.jpg\",\"datePublished\":\"2016-02-10T08:03:49+00:00\",\"dateModified\":\"2026-03-17T07:00:07+00:00\",\"description\":\"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/artikelbild-webcomponents.jpg\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/artikelbild-webcomponents.jpg\",\"width\":2300,\"height\":678,\"caption\":\"Foto von einem Laptop auf dessen Tastatur ein Hammer und ein Schraubenzieher liegt.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/webcomponents-tutorial\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Components selbst erstellen mit Polymer 1.0 [Tutorial]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/b2a8264915f219e25944c259e182a67f\",\"name\":\"Patrick Hillert\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/ich_profil_aff-96x96.jpg429eadbcccefd9b4c53b6f34afcd485d\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/ich_profil_aff-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/ich_profil_aff-96x96.jpg\",\"caption\":\"Patrick Hillert\"},\"description\":\"Web Software Developer &amp; Author - Web Components, StencilJS, Angular, Vue.js, Ruby on Rails, Docker, GitLab CI. I drive the change to discover, onboard, build, and scale apps that complement inovex vision of innovation and excellence. Setting the vision and strategy for developer experience and engineering community, including partners and customers. Offering mentorship, support and best-practices to minimize developer pain. I\u2019m responsible for partner engineering, developer relations, technical recommendations and best practices, sample apps, tech docs and the next-level developer training experience.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/patrick-hillert-a5b383206\\\/\",\"https:\\\/\\\/x.com\\\/silentHoo\"],\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/phillert\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH","description":"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/","og_locale":"de_DE","og_type":"article","og_title":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH","og_description":"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.","og_url":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2016-02-10T08:03:49+00:00","article_modified_time":"2026-03-17T07:00:07+00:00","og_image":[{"width":2300,"height":678,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg","type":"image\/jpeg"}],"author":"Patrick Hillert, Johannes Reuter","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents-1024x302.jpg","twitter_creator":"@silentHoo","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Patrick Hillert","Gesch\u00e4tzte Lesezeit":"16\u00a0Minuten","Written by":"Patrick Hillert, Johannes Reuter"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/"},"author":{"name":"Patrick Hillert","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b2a8264915f219e25944c259e182a67f"},"headline":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial]","datePublished":"2016-02-10T08:03:49+00:00","dateModified":"2026-03-17T07:00:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/"},"wordCount":2751,"commentCount":3,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg","keywords":["Web"],"articleSection":["Applications","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/","url":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/","name":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial] - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg","datePublished":"2016-02-10T08:03:49+00:00","dateModified":"2026-03-17T07:00:07+00:00","description":"Es wird auf gezeigt, wie eine Webkomponente mit Polymer 1.0 erstellt wird und welche Aufgaben durch Tools automatisiert werden k\u00f6nnen.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/02\/artikelbild-webcomponents.jpg","width":2300,"height":678,"caption":"Foto von einem Laptop auf dessen Tastatur ein Hammer und ein Schraubenzieher liegt."},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/webcomponents-tutorial\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Web Components selbst erstellen mit Polymer 1.0 [Tutorial]"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b2a8264915f219e25944c259e182a67f","name":"Patrick Hillert","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/wp-content\/uploads\/ich_profil_aff-96x96.jpg429eadbcccefd9b4c53b6f34afcd485d","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/ich_profil_aff-96x96.jpg","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/ich_profil_aff-96x96.jpg","caption":"Patrick Hillert"},"description":"Web Software Developer &amp; Author - Web Components, StencilJS, Angular, Vue.js, Ruby on Rails, Docker, GitLab CI. I drive the change to discover, onboard, build, and scale apps that complement inovex vision of innovation and excellence. Setting the vision and strategy for developer experience and engineering community, including partners and customers. Offering mentorship, support and best-practices to minimize developer pain. I\u2019m responsible for partner engineering, developer relations, technical recommendations and best practices, sample apps, tech docs and the next-level developer training experience.","sameAs":["https:\/\/www.linkedin.com\/in\/patrick-hillert-a5b383206\/","https:\/\/x.com\/silentHoo"],"url":"https:\/\/www.inovex.de\/de\/blog\/author\/phillert\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/1380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/77"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=1380"}],"version-history":[{"count":2,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/1380\/revisions"}],"predecessor-version":[{"id":66543,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/1380\/revisions\/66543"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/1387"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=1380"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=1380"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=1380"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=1380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}