{"id":39928,"date":"2021-09-09T11:28:29","date_gmt":"2021-09-09T09:28:29","guid":{"rendered":"https:\/\/kinsta.com\/?p=98073"},"modified":"2023-11-08T08:59:12","modified_gmt":"2023-11-08T07:59:12","slug":"web-components","status":"publish","type":"post","link":"https:\/\/kinsta.com\/nl\/blog\/web-components\/","title":{"rendered":"Een volledige introductie over Web Components"},"content":{"rendered":"<p>We hebben allemaal wel een paar projecten waar we liever niet aan werken. De code is onbeheersbaar geworden, de scope te groot, er zijn noodoplossingen gemaakt voor noodoplossingen, en de structuur is volledig verdwenen in een spaghetti van code. Programmeren kan soms ook erg rommelig zijn.<\/p>\n<p>Projecten kunnen dan ook profiteren van eenvoudige, onafhankelijke modules die allemaal maar \u00e9\u00e9n verantwoordelijkheid hebben. Deze modulaire code staat in feite los van elkaar, dus zelfvoorzienend, en de implementatie is daardoor veel makkelijker. Zolang je maar weet wat de module als output geeft op basis van een aantal inputs, hoef je niet per se precies te weten <em>hoe<\/em> dat resultaat geproduceerd wordt.<\/p>\n<p>Het toepassen van modulaire concepten op een enkele <a href=\"https:\/\/kinsta.com\/nl\/blog\/beste-programmeertaal-om-te-leren\/\">programmeertaal<\/a> is vrij helder, maar webdevelopment vereist meestal een brede mix van technologie\u00ebn. <a href=\"https:\/\/kinsta.com\/nl\/marktaandeel-desktopbrowsers\/\">Browsers<\/a> verwerken <a href=\"https:\/\/kinsta.com\/nl\/blog\/html-vs-html5\/\">HTML<\/a>, CSS en JavaScript om de content, stijlen en functionaliteit van een pagina te kunnen tonen.<\/p>\n<p>Dit betekent dat je niet zomaar alles kan mixen, omdat:<\/p>\n<ul>\n<li>Bij elkaar horende code kan zomaar over drie of meer bestanden verdeeld zijn, en<\/li>\n<li>Globale stijlen en JavaScript objecten kunnen op onverwachte manieren met elkaar reageren.<\/li>\n<\/ul>\n<p>Deze problemen komen nog bovenop de uitdagingen door verschillende runtimes van talen, <a href=\"https:\/\/kinsta.com\/nl\/blog\/javascript-bibliotheken\/\">frameworks<\/a>, databases en andere afhankelijkheden op de server.<\/p>\n<h3>Check onze <a href=\"https:\/\/www.youtube.com\/watch?v=hVxZ-te0kio\">videohandleiding<\/a> over webcomponenten<\/h3>\n<kinsta-video src=\"https:\/\/www.youtube.com\/watch?v=hVxZ-te0kio\"><\/kinsta-video>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc>\n<h2>Wat zijn Web Components?<\/h2>\n<p>Een Web Component is een manier om een <em>encapsulated, <\/em>op zichzelf staand stuk code te maken met \u00e9\u00e9n enkele verantwoordelijkheid, die je kan hergebruiken op elke willekeurige pagina.<\/p>\n<p>Denk eens aan de HTML\u00a0<code><strong>&lt;video&gt;<\/strong><\/code>\u00a0tag. Als je die implementeert op een willekeurige <a href=\"https:\/\/kinsta.com\/nl\/blog\/wat-is-een-url\/\">URL<\/a>, dan kan een bezoeker meteen allerlei dingen doen, zoals de video afspelen, pauzeren, het volume aanpassen en vooruit spoelen.<\/p>\n<p>Styling en functionaliteit zitten al ingebakken, alhoewel je ook aanpassingen kan maken via verschillende attributen en JavaScript API calls. Een willekeurig aantal <code><strong>&lt;video&gt;<\/strong><\/code> elementen kan in de tags geplaatst worden, zonder conflicten.<\/p>\n<p>Wat als je een eigen custom functie nodig hebt? Stel een element met daarin het aantal woorden op een bepaalde pagina? Er bestaat (nog) geen HTML\u00a0<code><strong>&lt;wordcount&gt;<\/strong><\/code>\u00a0tag.<\/p>\n<p>Frameworks zoals\u00a0<a href=\"https:\/\/kinsta.com\/nl\/blog\/javascript-bibliotheken\/#reactjs\">React<\/a>\u00a0of <a href=\"https:\/\/kinsta.com\/nl\/blog\/vue-js\/\">Vue.js<\/a>\u00a0bieden developers de mogelijkheid om onderdelen te maken waarbij de content, stijl, en functionaliteit binnen \u00e9\u00e9n JavaScript bestand aangemaakt kunnen worden. Dit kan een aantal ingewikkelde problemen bij het programmeren oplossen, maar bedenk daarbij wel dat:<\/p>\n<ul>\n<li>Je eerst dat framework moet leren gebruiken, en je code zal moeten updaten wanneer het framework verandert.<\/li>\n<li>Een onderdeel voor het ene framework zelden perfect compatibel is met een ander framework.<\/li>\n<li>Frameworks komen en gaan. Je bent volledig afhankelijk van de prioriteiten en plannen van het developmentteam en de gebruikers.<\/li>\n<li>Standaard Web Components kunnen functionaliteit aan de browser toevoegen, wat lastig te bereiken is in alleen JavaScript (zoals de Shadow DOM).<\/li>\n<\/ul>\n<p>Gelukkig worden populaire concepten binnen libraries en frameworks meestal snel overgenomen door webstandaarden. Het heeft even geduurd, maar Web Components zijn er inmiddels inderdaad.<\/p>\n\n<h2>Het ontstaan van Web Components<\/h2>\n<p>Follo<\/p>\n<p>Na diverse vendor-specifieke mislukking, is het concept van standaard Web Components voor het eerst ge\u00efntroduceerd door <a href=\"https:\/\/fronteers.nl\/congres\/2011\/sessions\/web-components-and-model-driven-views-alex-russell\">Alex Russell op de Fronteers Conference in 2011<\/a>. De <a href=\"https:\/\/github.com\/Polymer\/polymer\">Polymer library<\/a> van Google (een polyfill op basis van huidige voorstellen) kwam twee jaar later, maar de echte eerste implementaties verschenen pas in 2016 in Chrome en Safari.<\/p>\n<p>Browserproviders namen hun tijd om de details uit te werken, maar Web Components werden uiteindelijk toegevoegd aan Firefox in 2018 en aan Edge in 2020 (toen Microsoft overstapte naar Chromium).<\/p>\n<p>Het is begrijpelijk dat weinig webdevelopers stonden te springen om met Web Components aan de slag te gaan, maar inmiddels is er redelijk wat ondersteuning van browsers, met stabiele API&#8217;s. Niet alles is al helemaal perfect, maar het is een steeds beter alternatief voor framework-specifieke componenten.<\/p>\n<p>Zelfs als je jouw favoriete framework nog niet los wil laten, zijn Web Components compatibel met <em>elk<\/em> framework, en zullen alle API&#8217;s de komende jaren ook ondersteuning gaan krijgen.<\/p>\n<p>Verzamelingen met kant-en-klare Web Components zijn beschikbaar voor iedereen:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.webcomponents.org\/\">WebComponents.org<\/a><\/li>\n<li><a href=\"https:\/\/component.gallery\/\">The Component Gallery<\/a><\/li>\n<li><a href=\"https:\/\/genericcomponents.netlify.app\/\">generic-components<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/mdn\/web-components-examples\">web-components-examples<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/davatron5000\/awesome-standalones\">awesome-standalones<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/scottaohara\/accessible_components\">accessible_components<\/a><\/li>\n<li><a href=\"https:\/\/kickstand-ui.com\/\">Kickstand UI<\/a><\/li>\n<\/ul>\n<p>&#8230;maar het schrijven van je eigen code is natuurlijk altijd leuker.<\/p>\n<p>Deze tutorial biedt een complete introductie over Web Components, geschreven zonder een JavaScript framework. Je leert precies wat het zijn en hoe je ze kan gebruiken voor je eigen webprojecten. Je hebt wel wat basiskennis van <a href=\"https:\/\/kinsta.com\/nl\/blog\/html-vs-html5\/\">HTML5<\/a>, CSS en JavaScript nodig om alles goed te kunnen volgen.<\/p>\n<h2>Beginnen met Web Components<\/h2>\n<p>Web Components zijn custom HTML elementen, zoals\u00a0<code><strong>&lt;hello-world&gt;&lt;\/hello-world&gt;<\/strong><\/code>. De naam moet een koppelteken (dash) bevatten zodat het nooit problemen oplevert met elementen die officieel ondersteund worden in de HTML specificatie.<\/p>\n<p>Je moet een ES2015 class defini\u00ebren om het element te controleren. Dit kan elke willekeurige naam zijn, maar HelloWorld wordt veel gebruikt. Het moet een uitbreiding zijn van de <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/HTMLElement\">HTMLElement interface<\/a>, die de standaard eigenschappen en methoden van elk HTML element weergeeft.<\/p>\n<p><strong>Opmerking:<\/strong>\u00a0<a href=\"https:\/\/kinsta.com\/nl\/blog\/veiligste-browsers\/#3-firefox\">Firefox<\/a>\u00a0biedt de mogelijkheid tot uitbreiding van specifieke HTML elementen, zoals HTMLParagraphElement, HTMLImageElement, en HTMLButtonElement. Dit wordt niet ondersteund in andere browsers, en je kan zo geen Shadow DOM maken.<\/p>\n<p>Om er iets nuttigs mee te kunnen doen, heeft de class een methode nodig met de naam\u00a0<strong>connectedCallback()<\/strong>\u00a0die aangeroepen wordt wanneer het element wordt toegevoegd aan een document:<\/p>\n<pre><code class=\"language-html\">class HelloWorld extends HTMLElement {\n\n  \/\/ connect component\n  connectedCallback() {\n    this.textContent = 'Hello World!';\n  }\n\n}\n<\/code><\/pre>\n<p>In dit voorbeeld is de tekst van het element op &#8220;Hello World&#8221; ingesteld.<\/p>\n<p>De class moet geregistreerd zijn in de\u00a0<a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/CustomElementRegistry\">CustomElementRegistry<\/a> om het te defini\u00ebren als een handler voor een specifiek element:<\/p>\n<pre><code class=\"language-html\">customElements.define( 'hello-world', HelloWorld );\n<\/code><\/pre>\n<p>De browsers associeert nu het\u00a0<code><strong>&lt;hello-world&gt;<\/strong><\/code>\u00a0element met je <strong>HelloWorld<\/strong>\u00a0class wanneer je JavaScript geladen wordt (bijv.\u00a0 <code><b>&lt;script type=\"module\" src=\".\/helloworld.js\"&gt;&lt;\/script&gt;<\/b><\/code>).<\/p>\n<p>Je hebt nu een eigen element gemaakt!<\/p>\n<p><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" title=\"&lt;hello-world&gt; component\" src=\"https:\/\/codepen.io\/craigbuckler\/embed\/preview\/WNpaxPN?default-tabs=js%2Cresult&#038;height=300&#038;host=https%3A%2F%2Fcodepen.io&#038;slug-hash=WNpaxPN#?secret=N1Ld6A1NEX\" data-secret=\"N1Ld6A1NEX\" scrolling=\"no\" frameborder=\"0\" height=\"300\"><\/iframe><\/p>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/WNpaxPN\">CodePen demonstratie<\/a><\/p>\n<p>Dit onderdeel kan in CSS gestyled worden, net als andere elementen:<\/p>\n<pre><code class=\"language-css\">hello-world {\n  font-weight: bold;\n  color: red;\n}\n<\/code><\/pre>\n<h3>Toevoegen van attributen<\/h3>\n<p>Dit onderdeel biedt geen toegevoegde waarde aangezien dezelfde tekst al wordt getoond. Net als bij andere elementen, kunnen we HTML attributen toevoegen:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Dit kan de tekst overschrijven, zodat &#8220;Hello Craig!&#8221; wordt weergegeven. Om dit te doen kan je een\u00a0<strong>constructor()<\/strong>\u00a0functie toevoegen aan de <strong>HelloWorld<\/strong>\u00a0class, die wordt uitgevoerd wanneer een object wordt aangemaakt. Daarbij moeten:<\/p>\n<ol>\n<li>de <strong>super()<\/strong> method gecalld worden om de parent HTMLElement te initialiseren en<\/li>\n<li>andere initialisaties gedaan worden. In dit geval zullen we een <strong>name<\/strong> eigenschap defini\u00ebren die ingesteld staat op de standaardwaarde &#8220;World&#8221;:<\/li>\n<\/ol>\n<pre><code class=\"language-js\">class HelloWorld extends HTMLElement {\n\n  constructor() {\n    super();\n    this.name = 'World';\n  }\n\n  \/\/ more code...\n<\/code><\/pre>\n<p>Voor je component draait het alleen om de <strong>name<\/strong> attribuut. Een statische\u00a0<strong>observedAttributes()<\/strong>\u00a0eigenschap kan een array van eigenschappen teruggeven als antwoord:<\/p>\n<pre><code class=\"language-js\">\/\/ component attributes\nstatic get observedAttributes() {\n  return ['name'];\n}\n<\/code><\/pre>\n<p>Een <strong>attributeChangedCallback()<\/strong>\u00a0methode wordt gebruikt wanneer een attribuut wordt gedefinieerd in de HTML, of wordt gewijzigd via JavaScript. Daarbij wordt de naam van de eigenschap, de oude en de nieuwe waarde meegegeven:<\/p>\n<pre><code class=\"language-js\">\/\/ attribute change\nattributeChangedCallback(property, oldValue, newValue) {\n\n  if (oldValue === newValue) return;\n  this[ property ] = newValue;\n\n}\n<\/code><\/pre>\n<p>In dit voorbeeld zou alleen de <strong>name<\/strong> eigenschap ooit worden bijgewerkt, maar je zou ook meer eigenschappen kunnen toevoegen.<\/p>\n<p>Als laatste moet je het bericht in de\u00a0<strong>connectedCallback()<\/strong>\u00a0methode aanpassen:<\/p>\n<pre><code class=\"language-js\">\/\/ connect component\nconnectedCallback() {\n\n  this.textContent = `Hello ${ this.name }!`;\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/BaWqLOK\">CodePen demonstratie<\/a><\/p>\n<h3>Lifecycle methodes<\/h3>\n<p>De browser callt automatisch zes verschillende methodes tijdens de Web Component state. De hele lijst staat hieronder, al heb je inmiddels de eerste vier al gezien in bovenstaande voorbeelden:<\/p>\n<h4>constructor()<\/h4>\n<p>Dit wordt gecalld wanneer de component voor het eerst ge\u00efnitialiseerd wordt. Dit moet de <strong>super()<\/strong> aanroepen en kan eventuele standaardwaarden instellen of andere pre-rendering processen uitvoeren.<\/p>\n<h4>static observedAttributes()<\/h4>\n<p>Stuurt een array van attributen terug die de browser kan zien.<\/p>\n<h4>attributeChangedCallback(propertyName,<b> oldValue, newValue)<\/b><\/h4>\n<p>Wordt gecalld wanneer een geregistreerde attribuut wordt gewijzigd. De attributen die in HTML zijn gedefinieerd worden meteen doorgegeven, maar JavaScript kan ze nog wel aanpassen:<\/p>\n<pre><code class=\"language-js\">document.querySelector('hello-world').setAttribute('name', 'Everyone');\n<\/code><\/pre>\n<p>De methode moet soms een re-render uitvoeren wanneer dit gebeurt.<\/p>\n<h4>connectedCallback()<\/h4>\n<p>Deze functie wordt gecalld wanneer de Web Component aan een Document Object Model (DOM) wordt toegevoegd. Eventuele rendering zou daarna uitgevoerd moeten worden.<\/p>\n<h4>disconnectedCallback()<\/h4>\n<p>Dit wordt gecalled wanneer de Web Component wordt verwijderd van een DOM. Dit kan handig zijn als je de boel wat wil opruimen, wanneer je bijvoorbeeld een opgeslagen state wil verwijderen of een <a href=\"https:\/\/kinsta.com\/nl\/blog\/admin-ajax\/\">Ajax request<\/a> wil afbreken.<\/p>\n<h4>adoptedCallback()<\/h4>\n<p>Deze functie wordt gecalld wanneer een Web Component van het ene document naar het andere wordt verplaatst. Wellicht nuttig, al heb ik zelf nog geen toepassing gevonden.<\/p>\n<h2>Hoe Web Components samenwerken met andere onderdelen<\/h2>\n<p>Web Components bieden een aantal unieke functies die je niet in andere JavaScript frameworks kan vinden.<\/p>\n<h3>De Shadow DOM<\/h3>\n<p>Alhoewel bovenstaande Web Component al werkt, kan er van buitenaf mee geknoeid worden, en aangepast worden via CSS of JavaScript. Zo zouden ook de styles die je voor je component hebt aangemaakt naar buiten kunnen lekken.<\/p>\n<p>De Shadow DOM lost dit encapsulation probleem op door een apart DOM toe te voegen aan de Web Component, namelijk zo:<\/p>\n<pre><code class=\"language-js\">const shadow = this.attachShadow({ mode: 'closed' });\n<\/code><\/pre>\n<p>De mode kan ingesteld worden op:<\/p>\n<ol>\n<li><strong>\u201copen\u201d<\/strong>\u2014 JavaScript kan in de buitenste pagina verbinding maken met Shadow DOM (via <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Element\/shadowRoot\">Element.shadowRoot<\/a>), of<\/li>\n<li><strong>\u201cclosed\u201d<\/strong>\u2014 de Shadow DOM kan alleen geopend worden vanuit de Web Component.<\/li>\n<\/ol>\n<p>De Shadow DOM kan alleen gemanipuleerd worden zoals andere DOM elementen:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const shadow = this.attachShadow({ mode: 'closed' });\n\n  shadow.innerHTML = `\n    &lt;style&gt;\n      p {\n        text-align: center;\n        font-weight: normal;\n        padding: 1em;\n        margin: 0 0 2em 0;\n        background-color: #eee;\n        border: 1px solid #666;\n      }\n    &lt;\/style&gt;\n\n    &lt;p&gt;Hello ${ this.name }!&lt;\/p&gt;`;\n\n}\n<\/code><\/pre>\n<p>De component toont nu de tekst &#8220;Hello&#8221; binnen een <code><strong>&lt;p&gt;<\/strong><\/code> element en stijlt het ook zo. Het kan niet aangepast worden door JavaScript of CSS buiten de component, alhoewel sommige styles, zoals <a href=\"https:\/\/kinsta.com\/nl\/blog\/html-lettertypen\/\">font<\/a> en de kleur, worden ge\u00ebrfd vanaf de pagina aangezien ze niet expliciet gedefinieerd worden.<\/p>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/rNyqyJJ\">CodePen demonstratie<\/a><\/p>\n<p>De styles die door dit Web Component worden bepaald hebben geen effect op andere paragrafen op de pagina, of zelfs op andere <code><strong>&lt;hello-world&gt;<\/strong><\/code> componenten.<\/p>\n<p>Let op dat de CSS\u00a0<code>:host<\/code>\u00a0selector het buitenste\u00a0<code><strong>&lt;hello-world&gt;<\/strong><\/code>\u00a0element kan stylen vanuit de Web Component:<\/p>\n<pre><code class=\"language-css\">:host {\n  transform: rotate(180deg);\n}\n<\/code><\/pre>\n<p>Je kan de styles ook instellen om toegepast te worden wanneer het element een bepaalde class gebruikt, bijv.\u00a0<code><strong>&lt;hello-world class=\"rotate90\"&gt;<\/strong><\/code>:<\/p>\n<pre><code class=\"language-css\">:host(.rotate90) {\n  transform: rotate(90deg);\n}\n<\/code><\/pre>\n<h3>HTML Templates<\/h3>\n<p>Het defini\u00ebren van HTML kan al snel onpraktisch worden voor complexere Web Components. Een template maakt het mogelijk om een stuk HTML code in je pagina te defini\u00ebren die je Web Component dan kan gebruiken. Dit heeft diverse voordelen:<\/p>\n<ol>\n<li>Je kan HTML code eenvoudig aanpassen zonder dat je strings opnieuw moet schrijven in je JavaScript.<\/li>\n<li>Componenten kunnen aangepast worden zonder dat je voor elk type aparte JavaScript classes moet aanmaken.<\/li>\n<li>Het is eenvoudiger om HTML te defini\u00ebren binnen HTML, en het kan aangepast worden op de server of in de client vlak voor de component getoond wordt.<\/li>\n<\/ol>\n<p>Templates wordt gedefinieerd in een <code><strong>&lt;template&gt;<\/strong><\/code> tag, en het is praktisch om die een ID mee te geven zodat je deze kan refereren vanuit de component class. Dit voorbeeld toont drie paragrafen die allemaal &#8220;Hello&#8221; tonen:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;style&gt;\n    p {\n      text-align: center;\n      font-weight: normal;\n      padding: 0.5em;\n      margin: 1px 0;\n      background-color: #eee;\n      border: 1px solid #666;\n    }\n  &lt;\/style&gt;\n\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n\n&lt;\/template&gt;\n<\/code><\/pre>\n<p>De Web Component class kan deze template openen, de content lezen en de elementen <a href=\"https:\/\/kinsta.com\/nl\/blog\/kloon-wordpress-site\/\">klonen<\/a> om ervoor te zorgen dat je een uniek DOM fragment maakt overal waar dit wordt gebruikt:<\/p>\n<pre><code class=\"language-js\">const template = document.getElementById('hello-world').content.cloneNode(true);<\/code><\/pre>\n<p>De DOM kan aangepast worden en direct toegevoegd worden aan de Shadow DOM:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const\n\n    shadow = this.attachShadow({ mode: 'closed' }),\n    template = document.getElementById('hello-world').content.cloneNode(true),\n    hwMsg = `Hello ${ this.name }`;\n\n  Array.from( template.querySelectorAll('.hw-text') )\n    .forEach( n =&gt; n.textContent = hwMsg );\n\n  shadow.append( template );\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/QWpZvdQ\">CodePen demonstratie<\/a><\/p>\n<h3>Slots in templates<\/h3>\n<p>Slots zijn een soort fragmenten waarmee je een template kan aanpassen. Stel dat je het vorige <code><strong>&lt;hello-world&gt;<\/strong><\/code> Web Component wil gebruiken, maar het bericht wil plaatsen binnen een <strong>&lt;h1&gt;<\/strong> heading in de Shadow DOM. Dan kan je deze code schrijven:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>(Let op het <strong>slot <\/strong>attribuut.)<\/p>\n<p>Je zou ook andere elementen kunnen toevoegen, bijvoorbeeld een andere paragraaf:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Slots kunnen nu vanuit je template gebruikt worden:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n\n  &lt;slot&gt;&lt;\/slot&gt;\n\n&lt;\/template&gt;<\/code><\/pre>\n<p>Een element slot attribuut dat ingesteld is op \u201cmsgtext\u201d (de\u00a0<code><strong>&lt;h1&gt;<\/strong><\/code>) wordt ingevoegd wanneer er een\u00a0<code><strong>&lt;slot&gt;<\/strong><\/code>\u00a0is met de naam \u201cmsgtext.\u201d De <code><strong>&lt;p&gt;<\/strong><\/code>\u00a0tag heeft geen naam van een slot toegewezen gekregen, maar wordt gebruikt in de volgende\u00a0beschikbare <code><strong>&lt;slot&gt;<\/strong><\/code> zonder naam. Hierdoor wordt de template in feite zo:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;\n    &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;\/slot&gt;\n\n  &lt;slot&gt;\n    &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n  &lt;\/slot&gt;\n\n&lt;\/template&gt;\n<\/code><\/pre>\n<p>In de werkelijkheid is het natuurlijk niet helemaal zo simpel. Een <code><strong>&lt;slot&gt;<\/strong><\/code> element in de Shadow DOM <em>point<\/em> naar de ingevoegde elementen. Je kan ze alleen openen door een <code><strong>&lt;slot&gt;<\/strong><\/code> te vinden en dan de <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/HTMLSlotElement\/assignedNodes\">.assignedNodes() methode<\/a> te gebruiken om een array met de binnenste childs terug te sturen. De bijgewerkte\u00a0<strong>connectedCallback()<\/strong>\u00a0methode:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const\n    shadow = this.attachShadow({ mode: 'closed' }),\n    hwMsg = `Hello ${ this.name }`;\n\n  \/\/ append shadow DOM\n  shadow.append(\n    document.getElementById('hello-world').content.cloneNode(true)\n  );\n\n  \/\/ find all slots with a hw-text class\n  Array.from( shadow.querySelectorAll('slot.hw-text') )\n\n    \/\/ update first assignedNode in slot\n    .forEach( n =&gt; n.assignedNodes()[0].textContent = hwMsg );\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/gOmBBvm\">CodePen demonstratie<\/a><\/p>\n<p>Daarnaast kan je niet direct de ingevoegde elementen stylen, alhoewel je wel specifieke slots kan bewerken binnen je Web Component:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;style&gt;\n    slot[name=\"msgtext\"] { color: green; }\n  &lt;\/style&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n  &lt;slot&gt;&lt;\/slot&gt;\n\n&lt;\/template&gt;\n<\/code><\/pre>\n<p><a href=\"https:\/\/kinsta.com\/nl\/blog\/template-hierarchie-van-wordpress\/\">Template<\/a> slots zijn een beetje uitzonderlijk, maar een groot voordeel is dat je content ook getoond wordt wanneer JavaScript niet uitgevoerd kan worden. Onderstaande code toont een standaard heading en paragraph die alleen worden vervangen wanneer de Web Component class goed uitgevoerd kan worden:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Daarom kan je een soort progressieve berichten invoegen, zelfs gewoon een bericht met <em>&#8220;You need JavaScript&#8221;<\/em>.<\/p>\n<h3>De declaratieve Shadow DOM<\/h3>\n<p>De bovenstaande voorbeelden construeren een Shadow DOM op basis van JavaScript. Dat is momenteel de enige mogelijkheid, maar er wordt een experimentele Shadow DOM voor <a href=\"https:\/\/kinsta.com\/blog\/best-chrome-extensions\/\">Chrome<\/a> is in ontwikkeling. Dit maakt Server-Side Rendering mogelijk en voorkomt problemen met het verschuiven van de layout of ongestylde content.<\/p>\n<p>De volgende code kan worden gedetecteerd door de HTML parser, die een identieke Shadow DOM maakt als die je in de vorige sectie aangemaakt hebt (je kan eventueel het bericht aanpassen):<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;template shadowroot=\"closed\"&gt;\n    &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n    &lt;slot&gt;&lt;\/slot&gt;\n  &lt;\/template&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Deze feature is nog niet in elke browser beschikbaar, en we weten ook nog niet zeker of het in Firefox en Safari ge\u00efmplementeerd zal gaan worden. Je kan meer <a href=\"https:\/\/web.dev\/declarative-shadow-dom\/\">lezen over de declaratieve Shadow DOM<\/a> en een polyfill is vrij eenvoudig, maar het kan dus wel zijn dat de implementatie nog verandert.<\/p>\n<h3>Shadow DOM Events<\/h3>\n<p>Je Web Component kan events toevoegen aan elk element in de Shadow DOM, net zoals bij de pagina DOM, bijvoorbeeld het luisteren naar click events op onderliggende elementen:<\/p>\n<pre><code class=\"language-js\">shadow.addEventListener('click', e =&gt; {\n\n  \/\/ do something\n\n});\n<\/code><\/pre>\n<p>Tenzij je\u00a0<a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Event\/stopPropagation\">stopPropagation<\/a> gebruikt, zal het event opborrelen in de pagina DOM, maar het event zal wel een nieuw target krijgen. Daardoor lijkt het van je custom element te komen, niet van de onderliggende elementen.<\/p>\n<h2>Web Components gebruiken in andere frameworks<\/h2>\n<p>Elk Web Component dat je aanmaakt zal werken in alle <a href=\"https:\/\/kinsta.com\/nl\/blog\/javascript-bibliotheken\/#the-most-popular-javascript-frameworks\">JavaScript frameworks<\/a>. Die kennen allemaal niet het idee van HTML elementen, en je <code><strong>&lt;hello-world&gt;<\/strong><\/code> component zal daarom identiek worden behandeld als een normaal <code><strong>&lt;div&gt;<\/strong><\/code> element en in de DOM geplaatst worden, waar de class geactiveerd zal worden.<\/p>\n<p><a href=\"https:\/\/custom-elements-everywhere.com\/\">custom-elements-everywhere.com<\/a>\u00a0biedt een lijst met frameworks en opmerkingen over het gebruik van Web Components daarin. De meeste frameworks zijn volledig compatibel, al heeft React.js wel wat uitdagingen. Het is bijvoorbeeld mogelijk om <code><strong>&lt;hello-world&gt;<\/strong><\/code> te gebruiken in JSX:<\/p>\n<pre><code class=\"language-js\">import React from 'react';\nimport ReactDOM from 'react-dom';\nimport from '.\/hello-world.js';\n\nfunction MyPage() {\n\n  return (\n    &lt;&gt;\n      &lt;hello-world name=\"Craig\"&gt;&lt;\/hello-world&gt; \n    &lt;\/&gt;\n  );\n\n}\n\nReactDOM.render(&lt;MyPage \/&gt;, document.getElementById('root'));\n<\/code><\/pre>\n<p>\u2026maar:<\/p>\n<ul>\n<li>React kan alleen primaire datatypen doorsturen naar HTML attributen, dus geen arrays of objecten.<\/li>\n<li>React kan ook niet luisteren naar Web Component events, dus je moet handmatig je eigen handlers toevoegen.<\/li>\n<\/ul>\n<h2>Kritiek over en problemen met Web Components<\/h2>\n<p>Web Components zijn aanzienlijk verbeterd de laatste tijd, maar er zijn nog enkele aspecten die lastig blijven.<\/p>\n<h3>Moeite met styling<\/h3>\n<p>Het stylen van Web Components biedt een aantal uitdagingen, zeker als je styles binnen een scope wil overschrijven. Er zijn gelukkig allerlei oplossingen:<\/p>\n<ol>\n<li><strong>Gebruik niet de Shadow DOM.<\/strong> Je kan de content direct toevoegen aan je custom element, alhoewel een ander JavaScript script dit dan nog wel per ongeluk of opzettelijk kan wijzigen.<\/li>\n<li><strong>Gebruik de <\/strong><code><strong>:host<\/strong><\/code> <strong>classes.<\/strong> Zoals we eerder zagen kan <a href=\"https:\/\/kinsta.com\/blog\/critical-rendering-path\/#optimize-css\">scoped CSS<\/a> specifieke stylen toepassen wanneer een class wordt toegepast op een custom element.<\/li>\n<li><strong>Controleer de CSS custom eigenschappen (variabelen).<\/strong> Custom eigenschappen kunnen naar Web Components doorgezet worden, dus als je element <code><strong>var(--my-color)<\/strong><\/code> gebruikt, kan je <code><strong>--my-color<\/strong><\/code> in een buitenste container (zoals <code><strong>:root<\/strong><\/code>) zetten, en dan zal het gebruikt worden.<\/li>\n<li><strong>Doe je voordeel met &#8216;shadow&#8217; onderdelen.<\/strong> De nieuwe <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/CSS\/::part\">::part() selector<\/a> kan een binnenste component met een &#8216;part&#8217; attribuut stylen, dus <code><strong>&lt;h1 part=\"heading\"&gt;<\/strong><\/code> binnen een <code><strong>&lt;hello-world&gt;<\/strong><\/code> component kan gestyled worden met de selector <code><strong>hello-world::part(heading)<\/strong><\/code>.<\/li>\n<li><strong>Voer een string met styles door.<\/strong> Je kan deze doorgeven als een attribuut die binnen een <code><strong>&lt;style&gt;<\/strong><\/code> block toegepast kan worden.<\/li>\n<\/ol>\n<p>Dergelijke oplossingen zijn niet ideaal, en je moet goed nadenken over hoe andere gebruikers je Web Component kunnen aanpassen.<\/p>\n<h3>Genegeerde inputs<\/h3>\n<p>De velden <code><strong>&lt;input&gt;<\/strong><\/code>,\u00a0<code><strong>&lt;textarea&gt;<\/strong><\/code>, of\u00a0<code><strong>&lt;select&gt;<\/strong><\/code> in je Shadow DOM worden niet automatisch geassocieerd met het omvattende formulier. Vroege gebruikers van Web Component voegen verborgen velden toe aan de pagina DOM of gebruikten de <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/FormData\">FormData interface<\/a> om waarden bij te werken. Beide oplossingen zijn niet erg praktisch, en verbreken de encapsulation van Web Component.<\/p>\n<p>De nieuwe ElementInternals interface biedt een Web Component de mogelijkheid om een\u00a0<a href=\"https:\/\/kinsta.com\/nl\/blog\/wordpress-hooks\/\">hook<\/a>\u00a0in het formulier te zetten zodat custom waarden en de validiteit gedefinieerd kunnen worden. Dit is al ge\u00efmplementeerd in Chrome, maar een <a href=\"https:\/\/www.npmjs.com\/package\/element-internals-polyfill\">polyfill is ook beschikbaar<\/a> voor andere browsers.<\/p>\n<p>Ter demonstratie maken we een eenvoudig\u00a0<code><strong>&lt;input-age name=\"your-age\"&gt;&lt;\/input-age&gt;<\/strong><\/code>\u00a0component. De class moet een statische\u00a0<strong>formAssociated\u00a0<\/strong>waarde op TRUE hebben staan en optioneel een\u00a0<strong>formAssociatedCallback()<\/strong>\u00a0methode die gecalld kan worden wanneer het buitenste formulier wordt gebruikt:<\/p>\n<pre><code class=\"language-js\">\/\/ &lt;input-age&gt; web component\nclass InputAge extends HTMLElement {\n\n  static formAssociated = true;\n\n  formAssociatedCallback(form) {\n    console.log('form associated:', form.id);\n  }\n<\/code><\/pre>\n<p>De constructor moet nu de\u00a0<strong>attachInternals()<\/strong>\u00a0methode uitvoeren, waarmee het component kan communiceren met het formulier en andere <a href=\"https:\/\/kinsta.com\/nl\/blog\/wat-is-javascript\/\">JavaScript code<\/a> die de waarde of de validatie wil weten:<\/p>\n<pre><code class=\"language-js\">  constructor() {\n\n    super();\n    this.internals = this.attachInternals();\n    this.setValue('');\n\n  }\n\n  \/\/ set form value\n\n  setValue(v) {\n\n    this.value = v;\n\n    this.internals.setFormValue(v);\n\n  }\n<\/code><\/pre>\n<p>De ElementInternal\u2019s\u00a0<strong>setFormValue()<\/strong>\u00a0methode stelt de waarde van het element in voor het parent formulier met een lege string (het kan ook een FormData object doorgeven met diverse naam\/waarde paren). Andere eigenschappen en methodes zijn onder meer:<\/p>\n<ul>\n<li><strong>form<\/strong>: het parent formulier<\/li>\n<li><strong>labels<\/strong>: een array van elementen met labels voor het component<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Constraint_validation\">Constraint Validation API<\/a> met opties zoals willValidate, checkValidity, en validationMessage<\/li>\n<\/ul>\n<p>De <strong>connectedCallback()<\/strong>\u00a0methode maakt een Shadow\u00a0<a href=\"https:\/\/kinsta.com\/blog\/critical-rendering-path\/#the-dom\">DOM<\/a>, net als eerder, maar moet ook het veld monitoren op wijzigingen, zodat <strong>setFormValue()<\/strong>uitgevoerd kan worden:<\/p>\n<pre><code class=\"language-js\">  connectedCallback() {\n\n    const shadow = this.attachShadow({ mode: 'closed' });\n\n    shadow.innerHTML = `\n      &lt;style&gt;input { width: 4em; }&lt;\/style&gt;\n      &lt;input type=\"number\" placeholder=\"age\" min=\"18\" max=\"120\" \/&gt;`;\n\n    \/\/ monitor input values\n    shadow.querySelector('input').addEventListener('input', e =&gt; {\n      this.setValue(e.target.value);\n    });\n\n  }\n<\/code><\/pre>\n<p>Je kan nu een HTML formulier maken met dit Web Component die op dezelfde manier werkt met andere velden:<\/p>\n<pre><code class=\"language-html\">&lt;form id=\"myform\"&gt;\n\n  &lt;input type=\"text\" name=\"your-name\" placeholder=\"name\" \/&gt;\n\n  &lt;input-age name=\"your-age\"&gt;&lt;\/input-age&gt;\n\n  &lt;button&gt;submit&lt;\/button&gt;\n\n&lt;\/form&gt;\n<\/code><\/pre>\n<p>Het werkt wel, maar het is wel een beetje ingewikkeld.<\/p>\n<p>Bekijk het maar eens in de <a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/JjWmxwo\">CodePen demonstratie<\/a>.<\/p>\n<p>Voor meer informatie kan je ook <a href=\"https:\/\/web.dev\/more-capable-form-controls\/\">dit artikel lezen over controls voor formulieren<\/a>.<\/p>\n\n<h2>Samenvatting<\/h2>\n<p>Er is moeite geweest met het vinden van consensus over en gebruik van Web Component, terwijl JavaScript frameworks flink zijn gegroeid in capaciteit. Als je van een framework zoals React, <a href=\"https:\/\/kinsta.com\/nl\/blog\/javascript-bibliotheken\/#vuejs\">Vue<\/a>, of\u00a0<a href=\"https:\/\/kinsta.com\/nl\/blog\/php-vs-angular\/#what-is-angular\">Angular<\/a> komt, kunnen Web Components nogal complex en onhandig lijken, zeker wanneer je features zoals data-binding en state beheer moet missen.<\/p>\n<p>Er zijn dan ook nog zeker veel verbeteringen mogelijk, maar de toekomst voor Web Components ziet er erg rooskleurig uit. Ze zijn framework onafhankelijk, lichtgewicht, snel en kunnen functionaliteit bieden die je niet in alle JavaScript zou kunnen gebruiken.<\/p>\n<p>Tien jaar geleden zouden weinig mensen een website aangaan zonder jQuery, maar browserproviders hebben de goede delen genomen en alternatieve ingebouwd (zoals querySelector). Hetzelfde zal gebeuren bij JavaScript frameworks, en Web Components zijn daarin een eerste stap.<\/p>\n<p><em>Heb je nog vragen over het gebruik van Web Components? Laten we erover praten in de reacties hieronder!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We hebben allemaal wel een paar projecten waar we liever niet aan werken. De code is onbeheersbaar geworden, de scope te groot, er zijn noodoplossingen gemaakt &#8230;<\/p>\n","protected":false},"author":188,"featured_media":39933,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[160,431],"topic":[884],"class_list":["post-39928","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-html","tag-javascript","topic-webdevelopment-tools"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Een volledige introductie over Web Components<\/title>\n<meta name=\"description\" content=\"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\" \/>\n<meta property=\"og:locale\" content=\"nl_NL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Een volledige introductie over Web Components\" \/>\n<meta property=\"og:description\" content=\"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-09T09:28:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-08T07:59:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Craig Buckler\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\" \/>\n<meta name=\"twitter:creator\" content=\"@craigbuckler\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_NL\" \/>\n<meta name=\"twitter:label1\" content=\"Geschreven door\" \/>\n\t<meta name=\"twitter:data1\" content=\"Craig Buckler\" \/>\n\t<meta name=\"twitter:label2\" content=\"Geschatte leestijd\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\"},\"author\":{\"name\":\"Craig Buckler\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/715d986404b06691ab3014e06596908e\"},\"headline\":\"Een volledige introductie over Web Components\",\"datePublished\":\"2021-09-09T09:28:29+00:00\",\"dateModified\":\"2023-11-08T07:59:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\"},\"wordCount\":3009,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\",\"keywords\":[\"html\",\"JavaScript\"],\"articleSection\":[\"Webdevelopment\"],\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\",\"url\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\",\"name\":\"Een volledige introductie over Web Components\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\",\"datePublished\":\"2021-09-09T09:28:29+00:00\",\"dateModified\":\"2023-11-08T07:59:12+00:00\",\"description\":\"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#breadcrumb\"},\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/nl\/blog\/web-components\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\",\"contentUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png\",\"width\":1460,\"height\":730,\"caption\":\"Een volledige introductie over Web Components in 2021\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/nl\/blog\/web-components\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/nl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Webdevelopment tools\",\"item\":\"https:\/\/kinsta.com\/nl\/onderwerpen\/webdevelopment-tools\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Een volledige introductie over Web Components\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/nl\/#website\",\"url\":\"https:\/\/kinsta.com\/nl\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Snelle, veilige, premium hostingoplossingen\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/nl\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"nl-NL\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/nl\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/nl\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/\",\"https:\/\/x.com\/Kinsta_NL\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/715d986404b06691ab3014e06596908e\",\"name\":\"Craig Buckler\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-NL\",\"@id\":\"https:\/\/kinsta.com\/nl\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g\",\"caption\":\"Craig Buckler\"},\"description\":\"Freelance UK web developer, writer, and speaker. Has been around a long time and rants about standards and performance.\",\"sameAs\":[\"https:\/\/craigbuckler.com\/\",\"https:\/\/www.linkedin.com\/in\/craigbuckler\",\"https:\/\/x.com\/craigbuckler\",\"https:\/\/www.youtube.com\/channel\/UCQwdl5oBTWGhifS6bRGADMQ\"],\"url\":\"https:\/\/kinsta.com\/nl\/blog\/author\/craigbuckler\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Een volledige introductie over Web Components","description":"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.","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:\/\/kinsta.com\/nl\/blog\/web-components\/","og_locale":"nl_NL","og_type":"article","og_title":"Een volledige introductie over Web Components","og_description":"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.","og_url":"https:\/\/kinsta.com\/nl\/blog\/web-components\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/","article_published_time":"2021-09-09T09:28:29+00:00","article_modified_time":"2023-11-08T07:59:12+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","type":"image\/png"}],"author":"Craig Buckler","twitter_card":"summary_large_image","twitter_description":"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.","twitter_image":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","twitter_creator":"@craigbuckler","twitter_site":"@Kinsta_NL","twitter_misc":{"Geschreven door":"Craig Buckler","Geschatte leestijd":"16 minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/"},"author":{"name":"Craig Buckler","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/715d986404b06691ab3014e06596908e"},"headline":"Een volledige introductie over Web Components","datePublished":"2021-09-09T09:28:29+00:00","dateModified":"2023-11-08T07:59:12+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/"},"wordCount":3009,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/nl\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","keywords":["html","JavaScript"],"articleSection":["Webdevelopment"],"inLanguage":"nl-NL","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/nl\/blog\/web-components\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/","url":"https:\/\/kinsta.com\/nl\/blog\/web-components\/","name":"Een volledige introductie over Web Components","isPartOf":{"@id":"https:\/\/kinsta.com\/nl\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","datePublished":"2021-09-09T09:28:29+00:00","dateModified":"2023-11-08T07:59:12+00:00","description":"Webcomponenten zijn een standaardmanier om herbruikbare en modulaire HTML-elementen te maken zonder een JavaScript-framework te gebruiken.","breadcrumb":{"@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#breadcrumb"},"inLanguage":"nl-NL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/nl\/blog\/web-components\/"]}]},{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#primaryimage","url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","contentUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2021\/09\/web-components-.png","width":1460,"height":730,"caption":"Een volledige introductie over Web Components in 2021"},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/nl\/blog\/web-components\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/nl\/"},{"@type":"ListItem","position":2,"name":"Webdevelopment tools","item":"https:\/\/kinsta.com\/nl\/onderwerpen\/webdevelopment-tools\/"},{"@type":"ListItem","position":3,"name":"Een volledige introductie over Web Components"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/nl\/#website","url":"https:\/\/kinsta.com\/nl\/","name":"Kinsta\u00ae","description":"Snelle, veilige, premium hostingoplossingen","publisher":{"@id":"https:\/\/kinsta.com\/nl\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/nl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"nl-NL"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/nl\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/nl\/","logo":{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/nl\/wp-content\/uploads\/sites\/7\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/nl\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Kinsta-Nederland-476213452787823\/","https:\/\/x.com\/Kinsta_NL","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/715d986404b06691ab3014e06596908e","name":"Craig Buckler","image":{"@type":"ImageObject","inLanguage":"nl-NL","@id":"https:\/\/kinsta.com\/nl\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g","caption":"Craig Buckler"},"description":"Freelance UK web developer, writer, and speaker. Has been around a long time and rants about standards and performance.","sameAs":["https:\/\/craigbuckler.com\/","https:\/\/www.linkedin.com\/in\/craigbuckler","https:\/\/x.com\/craigbuckler","https:\/\/www.youtube.com\/channel\/UCQwdl5oBTWGhifS6bRGADMQ"],"url":"https:\/\/kinsta.com\/nl\/blog\/author\/craigbuckler\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/39928","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/users\/188"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/comments?post=39928"}],"version-history":[{"count":12,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/39928\/revisions"}],"predecessor-version":[{"id":56454,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/posts\/39928\/revisions\/56454"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/en"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/de"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/es"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/pt"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/nl"},{"embeddable":true,"hreflang":"sv","title":"Swedish","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/se"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/translations\/jp"},{"href":"https:\/\/kinsta.com\/nl\/wp-json\/kinsta\/v1\/posts\/39928\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/media\/39933"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/media?parent=39928"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/tags?post=39928"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/nl\/wp-json\/wp\/v2\/topic?post=39928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}