Hoppa till innehåll

Webbkomponenter – en introduktion

Under resten av kursen bygger du dina gränssnitt som webbkomponenter: egna HTML-element som paketerar struktur, stil och beteende i en återanvändbar enhet. Den här artikeln ger dig en överblick. Detaljerna kommer under de närmaste veckorna, så här räcker det att du förstår idén och känner igen begreppen.

Tidsåtgång: Ungefär 10 minuter.

HTML har en fast uppsättning element: <p>, <button>, <img> och så vidare. Så fort du vill ha något mer, till exempel en språkväljare med flaggor eller ett kort som visar en användare, måste du bygga det av befintliga element plus CSS och JavaScript. Utan någon struktur hamnar den koden lätt utspridd över hela applikationen.

Med webbkomponenter kan du i stället skapa ett eget element, till exempel <user-card>, och använda det som vilket annat element som helst. All kod som hör till kortet ligger samlad i komponenten.

“Webbkomponenter” är inte en egen standard utan ett samlingsnamn för flera standarder som används tillsammans:

Webbkomponenter i mitten, omgivet av fyra standarder: custom elements för egna HTML-element (kursvecka 10), Shadow DOM för inkapslad struktur och stil (kursvecka 10), HTML templates för återanvändbar markup (kursvecka 9) och ES-moduler för paketering och laddning (kursvecka 8).
  • Custom elements låter dig registrera ett eget element och koppla det till en klass.
  • Shadow DOM ger elementet ett eget, inkapslat DOM-träd. CSS i komponenten läcker inte ut, och sidans CSS läcker inte in.
  • HTML templates (<template>) innehåller markup som inte visas direkt men kan klonas, till exempel varje gång en komponent skapas.
  • ES-moduler är inte en del av webbkomponentstandarderna i strikt mening, men det naturliga sättet att paketera och ladda dem. Dem har du redan läst om i artikeln om webbläsaren som körmiljö.

Ett custom element är en klass som ärver från HTMLElement och registreras med customElements.define():

customElements.define('hello-message',
class extends HTMLElement {
connectedCallback() {
this.textContent = 'Hej från ett eget element!'
}
}
)

Efter det kan elementet användas i HTML:

<hello-message></hello-message>

connectedCallback() anropas av webbläsaren när elementet läggs in i dokumentet. Det är en av flera livscykelmetoder du lär dig mer om i kursvecka 10. Där kommer du också att lägga innehållet i elementets shadow DOM i stället för att skriva direkt i textContent, men principen är densamma.

Klassen behöver inget namn, eftersom den bara används som argument till define(). Det minskar risken att du kopierar en komponentfil och glömmer att byta namn på klassen.

Vilka av följande strängar kan du skicka som första argument till customElements.define()?

  1. 'hello'
  2. 'hello-message'
  3. 'Hello-Message'
  4. 'x-1'
  5. 'font-face'

Bara 'hello-message' och 'x-1' är giltiga.

  • 'hello' saknar bindestreck. Alla inbyggda HTML-element saknar bindestreck, och standarden lovar att det förblir så. Kravet på ett bindestreck garanterar därför att ditt element aldrig krockar med ett framtida inbyggt element.
  • 'Hello-Message' innehåller versaler, vilket inte är tillåtet. Namnet ska vara i kebab-case, med bara gemener.
  • 'font-face' har bindestreck, men tillhör en kort lista reserverade namn som redan används av äldre SVG- och MathML-standarder.

Ett ogiltigt namn ger ett SyntaxError när define() anropas.

Fråga: vad händer med <hello-message />?

Section titled “Fråga: vad händer med <hello-message />?”

Anta att du är van vid JSX eller XML och därför skriver elementet med ett avslutande snedstreck:

<hello-message />
<p>Det här stycket kommer efter.</p>

Hur tolkar webbläsaren det?

I HTML är snedstrecket bara tillåtet på så kallade void-element, som <img /> och <br />, och även där ignoreras det. <hello-message /> tolkas därför som en starttagg utan sluttagg, och <p>-elementet hamnar inuti <hello-message>. När connectedCallback() sedan sätter textContent skrivs stycket över och försvinner från sidan.

Skriv alltid ut sluttaggen: <hello-message></hello-message>.

Kan du ärva från andra element än HTMLElement?

Section titled “Kan du ärva från andra element än HTMLElement?”

Inbyggda element är också klasser. Ett <img>-element är ett HTMLImageElement, som ärver från HTMLElement. Du kan dock inte skapa ett inbyggt element med new: new HTMLImageElement() ger felet Illegal constructor. I stället skapar du det med document.createElement('img'), något du får använda mycket från och med nästa vecka.

Det ligger nära till hands att vilja ärva från HTMLButtonElement för att få en egen knapp med allt beteende från en vanlig knapp.

Standarden har en mekanism för det, så kallade customized built-in elements, där elementet används som <button is="fancy-button">. Safari har dock valt att inte implementera den, och det finns inga tecken på att det kommer att ändras. I praktiken betyder det att du alltid ärver från HTMLElement, och att din komponent själv innehåller de inbyggda element den behöver, till exempel en <button> i sin shadow DOM.

Inspelningarna från 2021 nämner att webbkomponenter inte hade fullt stöd i alla webbläsare några år tidigare. I dag fungerar custom elements, shadow DOM och templates i alla moderna webbläsare, och standarderna har fortsatt att utvecklas. Några exempel, som du inte behöver i kursen men kan stöta på när du söker information:

  • Deklarativ shadow DOM (<template shadowrootmode="open">) gör det möjligt att skriva en komponents shadow DOM direkt i HTML, till exempel när sidan genereras på en server. Baseline sedan 2024.
  • Formulärkopplade element (ElementInternals) låter ett eget element delta i ett <form> på samma sätt som ett <input>, med värde och validering.
  • Delade stilmallar (adoptedStyleSheets) låter många komponenter dela samma CSS-objekt i stället för att varje komponent får en egen kopia.

Även ramverken har närmat sig standarden. React stöder sedan version 19 custom elements fullt ut, så webbkomponenter kan användas i React-applikationer, och flera ramverk, bland annat Svelte, Vue och Angular, kan kompilera sina komponenter till custom elements.

Varför webbkomponenter i den här kursen?

Section titled “Varför webbkomponenter i den här kursen?”
  • Det är webbstandarder. Det du lär dig fungerar i alla webbläsare utan bibliotek eller byggsteg och blir inte inaktuellt när nästa ramverk kommer.
  • Det bygger på det du redan kan. En komponent är en klass, med konstruktor, metoder och arv, precis som i kursveckorna 6 och 7.
  • Det ger struktur. JavaScript tvingar inte fram något särskilt sätt att organisera kod. Komponenter ger dig ett tydligt mönster att följa, och samma tänkande känner du igen när du senare lär dig ett ramverk.
Kursvecka Innehåll
9 DOM och HTML templates, grunden komponenterna bygger på
10 Custom elements och shadow DOM på riktigt
11 Händelser, och hur komponenter kommunicerar med omvärlden
13 Komposition: komponenter som består av andra komponenter

Vill du redan nu prova kan du använda studiefrågorna i veckans översikt tillsammans med en AI-assistent. Låt den förklara varje rad kod den föreslår.

CCBY