{"id":1839,"date":"2020-12-03T12:08:20","date_gmt":"2020-12-03T12:08:20","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?p=1839"},"modified":"2021-05-19T06:14:56","modified_gmt":"2021-05-19T06:14:56","slug":"web-components-teil-1","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/","title":{"rendered":"Web Components (Teil 1) \u2013 Wie man eigene Komponenten baut"},"content":{"rendered":"\n<p>So genannte &#8222;Web Components&#8220; sind eine M\u00f6glichkeit, wiederverwendbare UI-Komponenten f\u00fcr Web-Anwendungen zu bauen. Anders als bei etablierten Single-Page-App-Frameworks wie React oder Angular basiert das Komponenten-Modell aber auf Web-Standards. Da SPA-Frameworks aber weit mehr leisten als nur Komponenten zu bauen, stehen Web Components nicht in unmittelbarer Konkurrenz zu den etablierten Frameworks. Sie k\u00f6nnen diese aber sinnvoll erg\u00e4nzen. Insbesondere dann, wenn Komponenten \u00fcber Anwendungen mit verschiedenen Technologie-Stacks hinweg wiederverwendet werden sollen, k\u00f6nnen Web Components einen guten Dienst leisten.<\/p>\n\n\n\n<p>Im Detail verbergen sich aber doch einige T\u00fccken, wenn es um den Einsatz von Web Components in Single-Page-Anwendungen geht: W\u00e4hrend die Einbindung in Angular-Anwendungen relativ einfach funktioniert, gibt es insbesondere bei React-Anwendungen einiges zu beachten.<\/p>\n\n\n\n<p>Ob die &#8222;Schuld&#8220; hierf\u00fcr nun bei React oder dem Web-Components-Standard liegt, kommt auf die Perspektive an und ist nicht ganz so leicht zu beantworten. Es gibt aber auch Aspekte, bei denen Web Components auch in ihrer Kernkompetenz, dem Bauen von Komponenten den K\u00fcrzeren ziehen. Denn manches ist im Vergleich, z. B. mit React, unn\u00f6tig kompliziert oder unflexibel.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"319\" src=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_SPA-600x319.png\" alt=\"\" class=\"wp-image-1856\" srcset=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_SPA-600x319.png 600w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_SPA-640x340.png 640w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_SPA.png 720w\" sizes=\"auto, (max-width: 639px) 98vw, (max-width: 1199px) 64vw, 600px\" \/><figcaption><em>Abbildung 1: Web Components und SPA-Frameworks<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>In <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/topic\/web-components\/\">dieser Artikelreihe<\/a> soll es um diese und weitere Aspekte beim Zusammenspiel von Web Components und SPA-Frameworks, <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-2\/\">insbesondere React<\/a>, gehen. Im ersten Teil der Reihe liegt der Fokus aber zun\u00e4chst nur auf Web Components, was sich hinter dem Begriff verbirgt und wie man Web Components baut.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Was sind Web Components und wie baut man eigene Komponenten?<\/h2>\n\n\n\n<p>Hinter dem Begriff &#8222;Web Components&#8220; verbergen sich mehrere separate HTML-Spezifikationen, die verschiedene Aspekte beim Entwickeln eigener Komponenten behandeln. Es gibt also nicht &#8222;den einen&#8220; Standard f\u00fcr Web Components, sondern es handelt sich um eine <a href=\"https:\/\/github.com\/WICG\/webcomponents\" target=\"_blank\" rel=\"noreferrer noopener\">Kombination von mehreren Spezifikationen<\/a>.<\/p>\n\n\n\n<p>Die beiden wichtigsten sind &#8222;Custom Elements&#8220; und &#8222;Shadow DOM&#8220;. Die Custom-Elements-Spezifikation beschreibt u. a. die JavaScript-Basis-Klasse &#8222;HTMLElement&#8220;, von welcher eigene Komponenten abgeleitet werden m\u00fcssen. Diese Klasse stellt zahlreiche Lifecycle-Methoden bereit, mit denen auf diverse Ereignisse im Lebenszyklus der Komponente reagiert werden kann. Beispielsweise l\u00e4sst sich programmatisch darauf reagieren, dass die Komponente in einem Dokument eingehangen oder Attribute der Komponente gesetzt wurden. Entwickler und Entwicklerinnen einer Komponente k\u00f6nnen daraufhin die Darstellung der Komponente aktualisieren. Au\u00dferdem geh\u00f6rt zu Custom Elements die M\u00f6glichkeit, eigene Komponenten-Klassen unter einem bestimmten HTML-Tag zu registrieren, damit die Komponente anschlie\u00dfend im gesamten Dokument zur Verf\u00fcgung steht.<\/p>\n\n\n\n<p>Hinter &#8222;Shadow-DOM&#8220; verbirgt sich eine Technik, mit der f\u00fcr eine Komponente ein eigener DOM-Baum angelegt werden kann, der vom restlichen Dokument weitestgehend isoliert ist. Das bedeutet, dass zum Beispiel CSS-Eigenschaften, die global im Dokument gesetzt wurden, nicht im Shadow-DOM wirksam sind und in die andere Richtung auch CSS-Definitionen innerhalb einer Komponente keine Auswirkungen auf sonstige Elemente im Dokument haben. Das Ziel ist eine bessere Kapselung der Komponenten und die Vermeidung von unerw\u00fcnschten Seiteneffekten beim Einbinden von fremden Webkomponenten.<\/p>\n\n\n\n<p>Im folgenden Code-Block ist eine einfache Hallo-Welt-Komponente zu sehen, die ein Property f\u00fcr den Namen der zu gr\u00fc\u00dfenden Person enth\u00e4lt.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class HelloWorld extends HTMLElement {\n\n    person = \"\"\n\n    constructor() {\n        super();\n\n        this.attachShadow({mode: \"open\"})\n\n        this.shadowRoot.innerHTML = `\n            &lt;div>\n                &lt;p>Hello &lt;span id=\"personGreeting\">&lt;\/span>&lt;\/p>\n            &lt;\/div>\n        `\n    }\n\n    static get observedAttributes() {\n        return ['person']\n    }\n\n    attributeChangedCallback(name, oldValue, newValue) {\n        if(name === \"person\") {\n            if(this.person !== newValue) {\n                this.person = newValue\n                this.update()\n            }\n        }\n    }\n\n    update() {\n        this.shadowRoot.querySelector(\"#personGreeting\").textContent = this.person\n    }\n\n}\nwindow.customElements.define(\"app-hello-world\", HelloWorld)<\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Im Konstruktor der Komponente wird zun\u00e4chst f\u00fcr die Komponente ein eigener Shadow-DOM-Baum angelegt. Die Angabe &#8222;mode: open&#8220; bewirkt, dass trotz der Shadow-DOM-Barriere von au\u00dfen mittels JavaScript auf den DOM-Baum der Komponente zugegriffen werden kann.<\/p>\n\n\n\n<p>Anschlie\u00dfend wird der &#8222;shadowRoot&#8220;, also der Root-Knoten des Shadow-DOM, entsprechend unserer W\u00fcnsche gestaltet \u2013 hier mittels &#8222;innerHTML&#8220;.<\/p>\n\n\n\n<p>Mit &#8222;observedAttributes&#8220; erkl\u00e4ren wir, welche Attribute die Komponente haben soll bzw. bei welchen Attributen wir benachrichtigt werden m\u00f6chten (wir k\u00f6nnen hier also auch Standard-Attribute wie &#8222;class&#8220; angeben).<\/p>\n\n\n\n<p>Die Benachrichtigung findet \u00fcber die Methode &#8222;attributeChangedCallback&#8220; statt, die als Parameter den Namen des ge\u00e4nderten Attributs sowie den alten und neuen Wert erh\u00e4lt. Da wir in unserem Fall nur ein einziges Attribut in &#8222;observedAttributes&#8220; angegeben haben, w\u00e4re eine Pr\u00fcfung auf den Namen des Attributs eigentlich nicht notwendig. Bei mehreren Attributen muss aber stets geschaut werden, welches Attribut gerade ge\u00e4ndert wurde.<\/p>\n\n\n\n<p>In unserem Fall pr\u00fcfen wir zun\u00e4chst, ob sich der neue Wert tats\u00e4chlich vom bisherigen unterscheidet (wir werden sp\u00e4ter noch sehen, wie das zustande kommen kann). Anschlie\u00dfend setzen wir die Property &#8222;person&#8220;, die wir als Klassenvariable angelegt haben, auf den Wert des \u00fcbergebenen Attributs.<\/p>\n\n\n\n<p>Um die Darstellung der Komponente zu aktualisieren wurde im Beispiel die Methode &#8222;update&#8220; angelegt. Diese geh\u00f6rt nicht zum Custom-Elements-Standard, sondern dient hier nur dazu, die Update-Logik an einer Stelle zu sammeln. Darin holen wir das zuvor angelegte Span-Element mit der ID &#8222;person&#8220; aus dem Shadow-DOM und setzen dessen Text auf den Wert der &#8222;person&#8220;-Property.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"424\" src=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM-600x424.png\" alt=\"\" class=\"wp-image-1852\" srcset=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM-600x424.png 600w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM-1024x724.png 1024w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM-768x543.png 768w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM-640x452.png 640w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_Shadow_DOM.png 1125w\" sizes=\"auto, (max-width: 639px) 98vw, (max-width: 1199px) 64vw, 600px\" \/><figcaption><em>Abbildung 2: Shadow DOM<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Als letzten Schritt sieht man im Code-Beispiel, wie unsere Komponenten-Klasse mit dem Tag-Namen &#8222;app-hello-world&#8220; registriert wird. Wichtig ist hier, dass der Name mindestens ein Minus-Zeichen enth\u00e4lt. Diese Regel wurde geschaffen, um m\u00f6gliche Namens-Kollisionen mit zuk\u00fcnftigen Standard-HTML-Tags zu vermeiden. Es hat sich daher als zweckm\u00e4\u00dfig erwiesen, ein sinnvolles Pr\u00e4fix f\u00fcr eigene Komponenten zu w\u00e4hlen, um so auch Kollisionen mit anderen Komponenten-Bibliotheken m\u00f6glichst zu vermeiden (das im Beispiel gew\u00e4hlte Pr\u00e4fix &#8222;app&#8220; d\u00fcrfte in dieser Hinsicht kein gutes Vorbild sein). Ein wirklich sicherer Mechanismus zur Vermeidung von Konflikten existiert jedoch nicht.<\/p>\n\n\n\n<p>Mittels Attribute haben wir nun also die M\u00f6glichkeit, einfache Daten in die Komponente hineinzureichen. Beim Thema &#8222;Attribute&#8220; gibt es noch einige Besonderheiten und Fallstricke, die wir aber f\u00fcr den <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-2\/\">n\u00e4chsten Teil dieser Artikelreihe<\/a> aufheben wollen. F\u00fcr diese allgemeine Einf\u00fchrung wollen wir es erst einmal dabei belassen.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Slots<\/h2>\n\n\n\n<p>Ein weiteres wichtiges Feature von Web Components, welches uns ebenfalls in einem sp\u00e4teren Teil der Reihe nochmal besch\u00e4ftigen wird, sind die sogenannten Slots. Damit lassen sich HTML-Schnipsel an eine Komponente \u00fcbergeben. Die Komponente entscheidet dann, wie sie die \u00fcbergebenen Elemente darstellt. Wollen wir beispielsweise eine Hinweisbox bauen, die neben einem Text auch ein Icon darstellt und mit einem Rahmen umgibt, bietet es sich an, den Hinweistext nicht als Attribut, sondern mit einem Slot an die Komponente zu geben. Auf diese Weise sind wir nicht nur auf reinen Text beschr\u00e4nkt, sondern k\u00f6nnen beliebigen HTML-Content nutzen.<\/p>\n\n\n\n<p>In der Anwendung kann das beispielsweise so aussehen:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;app-notification-box>\n\t&lt;p>Some Text with additional &lt;strong>tags&lt;\/strong>&lt;\/p>\n&lt;\/app-notification-box><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Wir m\u00fcssen also nur die gew\u00fcnschten HTML-Tags als Kindelemente schreiben. Innerhalb der Komponente muss daf\u00fcr ein &lt;slot&gt;-Element im Shadow-Root auftauchen. Anstelle des Slot-Elements wird beim Rendering der Komponente dann der \u00fcbergebene Content angezeigt.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;div>\n    &lt;div>Icon&lt;\/div>\n    &lt;div id=\"content\">\n        &lt;slot>&lt;\/slot>\n    &lt;\/div>\n&lt;\/div><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Eine Komponente kann auch mehrere Slots enthalten. Damit der Browser aber entscheiden kann, welche HTML-Elemente er welchem Slot zuordnen soll, m\u00fcssen in diesem Fall sogenannte &#8222;Named Slots&#8220; benutzt werden, d. h. die Slots bekommen ein spezielles Name-Attribut. Nur h\u00f6chstens ein Slot darf innerhalb einer Komponente ohne Name-Attribut vorkommen. Bei diesem spricht man vom &#8222;Default Slot&#8220;. In der Komponente kann das z. B. so aussehen:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;div>\n    &lt;div id=\"header\">\n        &lt;h1>\n            &lt;slot name=\"header\">&lt;\/slot>\n        &lt;\/h1>\n    &lt;\/div>\n    &lt;div id=\"icon\">\n        &lt;slot name=\"icon\">&lt;\/slot>\n    &lt;\/div>\n    &lt;div id=\"content\">\n        &lt;slot>&lt;slot>\n    &lt;\/div>\n&lt;\/div><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Die Benutzung k\u00f6nnte dann z. B. so aussehen:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;app-notification-box>\n    &lt;p>Some Content&lt;\/p>\n    &lt;span slot=\"header\">A meaningful Header&lt;\/span>\n    &lt;img slot=\"icon\" src=\"...\" alt=\"notification icon\"\/>\n&lt;\/app-notification-box><\/pre>\n\n\n\n<p>Hier sieht man die Nutzung des &#8222;slot&#8220;-Attributs. Die Werte m\u00fcssen zu den &#8222;name&#8220;-Attributen an den Slots innerhalb der Komponente passen. Folglich geh\u00f6rt dies zum Teil der \u00f6ffentlichen API einer Komponente und muss entsprechend dokumentiert werden.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Events<\/h2>\n\n\n\n<p>Bisher haben wir nur gesehen, wie Daten in Komponenten hineingereicht werden k\u00f6nnen, jedoch noch nicht den umgekehrten Weg skizziert. Denn um wirklich interaktiv zu sein, m\u00fcssen Entwickler und Entwicklerinnen auch die M\u00f6glichkeit haben, auf bestimmte Ereignisse zu reagieren und Daten von der Komponente entgegenzunehmen.<\/p>\n\n\n\n<p>F\u00fcr diesen Zweck dienen bei HTML Events. Und auch diesen Aspekt wollen wir uns in diesem Artikel nur kurz anschauen und sp\u00e4ter genauer unter die Lupe nehmen.<\/p>\n\n\n\n<p>Web Components k\u00f6nnen sowohl Standard Events als auch Custom Events erzeugen.<\/p>\n\n\n\n<p>Standard-Events sind dann n\u00fctzlich, wenn die Art des Events so auch schon bei Standard-HTML-Elementen vorkommt und daher nicht neu erfunden werden muss, beispielsweise ein <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/KeyboardEvent\" target=\"_blank\" rel=\"noreferrer noopener\">KeyboardEvent<\/a>. Custom-Events sind dann sinnvoll, wenn zus\u00e4tzliche Daten als Payload dem Event mitgegeben werden sollen. Wenn wir beispielsweise eine eigene interaktive Tabellenkomponente bauen, in der die Nutzenden einzelne Zeilen selektieren k\u00f6nnen, bietet es sich m\u00f6glicherweise an, ein Event bei der Selektion auszul\u00f6sen&nbsp;, welches als Payload die Daten der gew\u00e4hlten Zeile enth\u00e4lt.<\/p>\n\n\n\n<p>Der Mechanismus zum Ausl\u00f6sen von Events ist f\u00fcr alle Arten von Events gleich. Dies ist im folgenden Code-Block zu sehen:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class InteractiveComponent extends HTMLElement {\n\n    triggerStandardEvent() {\n        const event = new Event(\"close\")\n        this.dispatchEvent(event)\n    }\n\n    triggerCustomEvent() {\n        const event = new CustomEvent(\"some-reason\", \n            { detail: { someData: \"...\" }}\n        )\n        this.dispatchEvent(event)\n    }\n}<\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Zur Erzeugung eines Events wird entweder direkt eine Instanz von &#8222;Event&#8220; oder <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Event\" target=\"_blank\" rel=\"noreferrer noopener\">eine der anderen Event-Klassen<\/a> (zu denen auch &#8222;CustomEvent&#8220; geh\u00f6rt) erzeugt. Alle Event-Konstruktoren erwarten als ersten Parameter den Type des Events. Dieser Typ wird sp\u00e4ter auch benutzt, um Listener f\u00fcr diese Events zu registrieren.<\/p>\n\n\n\n<p>Der zweite Parameter ist optional und stellt ein JavaScript-Objekt dar, welches das Event konfiguriert. F\u00fcr CustomEvent ist beispielsweise das Feld &#8222;detail&#8220; vorgesehen, um beliebige Payload-Daten zu \u00fcbergeben.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p>Der Artikel gibt eine kurze Einf\u00fchrung in das Thema &#8222;Web Components&#8220; und mit den gezeigten Techniken k\u00f6nnen bereits eigene Komponenten gebaut werden. Nat\u00fcrlich gibt es noch zahlreiche weitere Aspekte, die bei der Entwicklung von Web Components beachtet werden m\u00fcssen. Nicht umsonst f\u00fcllt das Thema so manches Fachbuch. In <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/topic\/web-components\/\">dieser Artikelreihe <\/a>wollen wir vor allem auf einige Fallstricke eingehen, die bei einzelnen Themen auftreten k\u00f6nnen und genauer beleuchten, wie diese umgangen werden k\u00f6nnen. Auch eine kritische Auseinandersetzung mit der Web-Components-API soll Teil dieser Serie werden. Insbesondere das Zusammenspiel mit SPA-Frameworks wird uns in den n\u00e4chsten Artikeln besch\u00e4ftigen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So genannte &#8222;Web Components&#8220; sind eine M\u00f6glichkeit, wiederverwendbare UI-Komponenten f\u00fcr Web-Anwendungen zu bauen. Anders als bei etablierten Single-Page-App-Frameworks wie React oder Angular basiert das Komponenten-Modell aber auf Web-Standards.<\/p>\n","protected":false},"author":18,"featured_media":1858,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[11],"tags":[169,170,208,236,304,337,575,576,577],"topics":[584],"class_list":["post-1839","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web","tag-angular","tag-webanwendung","tag-react","tag-webanwendungen","tag-web","tag-editorschoice","tag-web-components","tag-ui-komponenten","tag-spa-frameworks","topics-web-components"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Web Components (Teil 1) - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Web Components (Teil 1) - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-03T12:08:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-19T06:14:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1182\" \/>\n\t<meta property=\"og:image:height\" content=\"666\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manuel Mauky\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:site\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manuel Mauky\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"9\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/\",\"name\":\"Web Components (Teil 1) - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png\",\"datePublished\":\"2020-12-03T12:08:20+00:00\",\"dateModified\":\"2021-05-19T06:14:56+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/d7a29c5e55882a2841cfd79b4118132f\"},\"description\":\"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png\",\"width\":1182,\"height\":666},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Components (Teil 1) \u2013 Wie man eigene Komponenten baut\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/d7a29c5e55882a2841cfd79b4118132f\",\"name\":\"Manuel Mauky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/06\/Mauky_Manuel_Profilbild_300x300px-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/06\/Mauky_Manuel_Profilbild_300x300px-150x150.jpg\",\"caption\":\"Manuel Mauky\"},\"description\":\"Manuel arbeitet seit 2010 als Softwareentwickler bei der ZEISS Digital Innovation in G\u00f6rlitz. Neben Java besch\u00e4ftigt er sich vor allem mit JavaScript und TypeScript und der Entwicklung von modernen Webanwendungen. Au\u00dferdem interessiert er sich f\u00fcr Funktionale Programmierung und h\u00e4lt regelm\u00e4\u00dfig Vortr\u00e4ge zu diesen Themen. Manuel hat in G\u00f6rlitz Informatik studiert und organisiert die Java-User-Group G\u00f6rlitz.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/manuelmauky\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Web Components (Teil 1) - ZEISS Digital Innovation Blog","description":"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.","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:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/","og_locale":"de_DE","og_type":"article","og_title":"Web Components (Teil 1) - ZEISS Digital Innovation Blog","og_description":"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/","og_site_name":"Digital Innovation Blog","article_publisher":"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/","article_published_time":"2020-12-03T12:08:20+00:00","article_modified_time":"2021-05-19T06:14:56+00:00","og_image":[{"width":1182,"height":666,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png","type":"image\/png"}],"author":"Manuel Mauky","twitter_card":"summary_large_image","twitter_creator":"@ZEISS_di","twitter_site":"@ZEISS_di","twitter_misc":{"Verfasst von":"Manuel Mauky","Gesch\u00e4tzte Lesezeit":"9\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/","name":"Web Components (Teil 1) - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png","datePublished":"2020-12-03T12:08:20+00:00","dateModified":"2021-05-19T06:14:56+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/d7a29c5e55882a2841cfd79b4118132f"},"description":"Mit Web Components k\u00f6nnen wiederverwendbare UI-Komponenten f\u00fcr Webanwendungen gebaut werden. Das Komponenten-Modell basiert auf Web-Standards.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi.png","width":1182,"height":666},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/web-components-teil-1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/"},{"@type":"ListItem","position":2,"name":"Web Components (Teil 1) \u2013 Wie man eigene Komponenten baut"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/d7a29c5e55882a2841cfd79b4118132f","name":"Manuel Mauky","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/06\/Mauky_Manuel_Profilbild_300x300px-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2024\/06\/Mauky_Manuel_Profilbild_300x300px-150x150.jpg","caption":"Manuel Mauky"},"description":"Manuel arbeitet seit 2010 als Softwareentwickler bei der ZEISS Digital Innovation in G\u00f6rlitz. Neben Java besch\u00e4ftigt er sich vor allem mit JavaScript und TypeScript und der Entwicklung von modernen Webanwendungen. Au\u00dferdem interessiert er sich f\u00fcr Funktionale Programmierung und h\u00e4lt regelm\u00e4\u00dfig Vortr\u00e4ge zu diesen Themen. Manuel hat in G\u00f6rlitz Informatik studiert und organisiert die Java-User-Group G\u00f6rlitz.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/manuelmauky\/"}]}},"author_meta":{"display_name":"Manuel Mauky","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/manuelmauky\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/11\/202011_WebComponents_1_fi-600x338.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Web<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Angular<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Webanwendung<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">React<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Webanwendungen<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">web<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Editor&#039;s Choice<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Web Components<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">UI-Komponenten<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">SPA-Frameworks<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Angular<\/span>","<span class=\"advgb-post-tax-term\">Webanwendung<\/span>","<span class=\"advgb-post-tax-term\">React<\/span>","<span class=\"advgb-post-tax-term\">Webanwendungen<\/span>","<span class=\"advgb-post-tax-term\">web<\/span>","<span class=\"advgb-post-tax-term\">Editor&#039;s Choice<\/span>","<span class=\"advgb-post-tax-term\">Web Components<\/span>","<span class=\"advgb-post-tax-term\">UI-Komponenten<\/span>","<span class=\"advgb-post-tax-term\">SPA-Frameworks<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 5\u00a0Jahren ago","modified":"Updated 5\u00a0Jahren ago"},"absolute_dates":{"created":"Posted on Dezember 3, 2020","modified":"Updated on Mai 19, 2021"},"absolute_dates_time":{"created":"Posted on Dezember 3, 2020 12:08 p.m.","modified":"Updated on Mai 19, 2021 6:14 a.m."},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1839","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/comments?post=1839"}],"version-history":[{"count":15,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1839\/revisions"}],"predecessor-version":[{"id":2433,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1839\/revisions\/2433"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media\/1858"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media?parent=1839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/categories?post=1839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/tags?post=1839"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/topics?post=1839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}