Opbygning af interoperable webkomponenter, der endda fungerer med React PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Opbygning af interoperable webkomponenter, der endda fungerer med React

De af os, der har været webudviklere i mere end et par år, har sandsynligvis skrevet kode ved hjælp af mere end én JavaScript-ramme. Med alle valgmulighederne derude - React, Svelte, Vue, Angular, Solid - er det næsten uundgåeligt. En af de mere frustrerende ting, vi skal forholde os til, når vi arbejder på tværs af rammer, er at genskabe alle disse UI-komponenter på lavt niveau: knapper, faner, rullemenuer osv. Det, der er særligt frustrerende er, at vi typisk vil have dem defineret i én ramme. , siger React, men skal så omskrive dem, hvis vi vil bygge noget i Svelte. Eller Vue. Eller Solid. Og så videre.

Ville det ikke være bedre, hvis vi kunne definere disse UI-komponenter på lavt niveau én gang, på en ramme-agnostisk måde, og derefter genbruge dem mellem frameworks? Selvfølgelig ville det! Og vi kan; webkomponenter er vejen. Dette indlæg viser dig hvordan.

Lige nu mangler SSR-historien for webkomponenter en smule. Declarative shadow DOM (DSD) er, hvordan en webkomponent gengives på serversiden, men som dette skrives, er den ikke integreret med dine foretrukne applikationsrammer som Next, Remix eller SvelteKit. Hvis det er et krav for dig, skal du sørge for at tjekke den seneste status for DSD. Men ellers, hvis SSR ikke er noget du bruger, så læs videre.

Først lidt kontekst

Webkomponenter er grundlæggende HTML-elementer, som du selv definerer, f.eks <yummy-pizza> eller hvad som helst, fra bunden. De er dækket over det hele her på CSS-Tricks (inklusive en omfattende serie af Caleb Williams , en af ​​John Rhea), men vi vil kort gennemgå processen. Grundlæggende definerer du en JavaScript-klasse, arver den fra HTMLElement, og derefter definere hvilke egenskaber, attributter og stilarter webkomponenten har, og selvfølgelig den markup, den i sidste ende vil give dine brugere.

At være i stand til at definere tilpassede HTML-elementer, der ikke er bundet til nogen bestemt komponent, er spændende. Men denne frihed er også en begrænsning. Eksisterende uafhængigt af enhver JavaScript-ramme betyder, at du ikke rigtig kan interagere med disse JavaScript-rammer. Tænk på en React-komponent, som henter nogle data og derefter gengiver nogle andre Reaktionskomponent, videregiver dataene. Dette ville ikke rigtig fungere som en webkomponent, da en webkomponent ikke ved, hvordan man gengiver en React-komponent.

Webkomponenter udmærker sig især som bladkomponenter. Bladkomponenter er den sidste ting, der skal gengives i et komponenttræ. Det er de komponenter, der modtager nogle rekvisitter og gengiver nogle UI. Disse er ikke komponenterne, der sidder i midten af ​​dit komponenttræ, sender data videre, sætter kontekst osv. — bare rene stykker af UI det vil se det samme ud, uanset hvilken JavaScript-ramme der driver resten af ​​appen.

Webkomponenten, vi bygger

I stedet for at bygge noget kedeligt (og almindeligt), som en knap, lad os bygge noget lidt anderledes. I min lastning indlæg vi så på at bruge slørede billedforhåndsvisninger for at forhindre indholdsfornyelse og give brugerne en anstændig brugergrænseflade, mens vores billeder indlæses. Vi så på base64, der koder for en sløret, forringet version af vores billeder og viser det i vores brugergrænseflade, mens det rigtige billede blev indlæst. Vi så også på at generere utroligt kompakte, slørede forhåndsvisninger ved hjælp af et værktøj kaldet Blurhash.

Det indlæg viste dig, hvordan du genererer disse forhåndsvisninger og bruger dem i et React-projekt. Dette indlæg viser dig, hvordan du bruger disse forhåndsvisninger fra en webkomponent, så de kan bruges af enhver JavaScript-ramme.

Men vi er nødt til at gå, før vi kan løbe, så vi går gennem noget trivielt og fjollet først for at se præcis, hvordan webkomponenter fungerer.

Alt i dette indlæg vil bygge vanilje-webkomponenter uden noget værktøj. Det betyder, at koden vil have en smule kedelplade, men den burde være forholdsvis nem at følge. Værktøjer som Lit or Stencil er designet til at bygge webkomponenter og kan bruges til at fjerne meget af denne kedelplade. Jeg opfordrer dig til at tjekke dem ud! Men til dette indlæg foretrækker jeg lidt mere kedelsten til gengæld for ikke at skulle introducere og undervise i en anden afhængighed.

En simpel tællerkomponent

Lad os bygge den klassiske "Hello World" af JavaScript-komponenter: en tæller. Vi gengiver en værdi og en knap, der øger denne værdi. Simpelt og kedeligt, men det vil lade os se på den enklest mulige webkomponent.

For at bygge en webkomponent er det første skridt at lave en JavaScript-klasse, som arver fra HTMLElement:

class Counter extends HTMLElement {}

Det sidste trin er at registrere webkomponenten, men kun hvis vi ikke allerede har registreret den:

if (!customElements.get("counter-wc")) { customElements.define("counter-wc", Counter);
}

Og selvfølgelig gengiv det:

<counter-wc></counter-wc>

Og alt derimellem er, at vi får webkomponenten til at gøre, hvad vi vil have den til. En almindelig livscyklusmetode er connectedCallback, som udløses, når vores webkomponent føjes til DOM. Vi kunne bruge den metode til at gengive det indhold, vi gerne vil have. Husk, dette er en JS-klasse, der arver fra HTMLElement, hvilket betyder vores this værdi er selve webkomponentelementet med alle de normale DOM-manipulationsmetoder, du allerede kender og elsker.

På det enkleste kan vi gøre dette:

class Counter extends HTMLElement { connectedCallback() { this.innerHTML = "<div style='color: green'>Hey</div>"; }
} if (!customElements.get("counter-wc")) { customElements.define("counter-wc", Counter);
}

…hvilket vil fungere fint.

Ordet "hey" i grønt.
Opbygning af interoperable webkomponenter, der endda fungerer med React

Tilføjelse af ægte indhold

Lad os tilføje noget nyttigt, interaktivt indhold. Vi har brug for en <span> for at holde den aktuelle talværdi og en <button> for at øge tælleren. Indtil videre opretter vi dette indhold i vores konstruktør og tilføjer det, når webkomponenten faktisk er i DOM:

constructor() { super(); const container = document.createElement('div'); this.valSpan = document.createElement('span'); const increment = document.createElement('button'); increment.innerText = 'Increment'; increment.addEventListener('click', () => { this.#value = this.#currentValue + 1; }); container.appendChild(this.valSpan); container.appendChild(document.createElement('br')); container.appendChild(increment); this.container = container;
} connectedCallback() { this.appendChild(this.container); this.update();
}

Hvis du virkelig er træt af den manuelle DOM-oprettelse, så husk, at du kan indstille innerHTML, eller endda opret et skabelonelement én gang som en statisk egenskab for din webkomponentklasse, klon den og indsæt indholdet for nye webkomponentforekomster. Der er sikkert nogle andre muligheder, jeg ikke tænker på, eller du kan altid bruge en webkomponentramme som Lit or Stencil. Men for dette indlæg vil vi fortsætte med at holde det enkelt.

Går vi videre, har vi brug for en indstillelig JavaScript-klasseejendom med navnet value

#currentValue = 0; set #value(val) { this.#currentValue = val; this.update();
}

Det er bare en standardklasseejendom med en sætter sammen med en anden egenskab til at holde værdien. Et sjovt twist er, at jeg bruger den private JavaScript-klasseegenskabssyntaks til disse værdier. Det betyder, at ingen uden for vores webkomponent nogensinde kan røre ved disse værdier. Dette er standard JavaScript der understøttes i alle moderne browsere, så vær ikke bange for at bruge det.

Eller ring det gerne _value hvis du foretrækker det. Og til sidst vores update metode:

update() { this.valSpan.innerText = this.#currentValue;
}

Det virker!

Tællerwebkomponenten.
Opbygning af interoperable webkomponenter, der endda fungerer med React

Dette er naturligvis ikke kode, du ønsker at vedligeholde i skala. Her er en fuld arbejdseksempel hvis du vil have et nærmere kig. Som jeg har sagt, er værktøjer som Lit og Stencil designet til at gøre dette enklere.

Tilføjelse af mere funktionalitet

Dette indlæg er ikke et dybt dyk ned i webkomponenter. Vi dækker ikke alle API'er og livscyklusser; vi vil ikke engang dække skyggerødder eller slidser. Der er uendeligt med indhold om disse emner. Mit mål her er at give en anstændig nok introduktion til at vække en vis interesse, sammen med nogle nyttige vejledninger om faktisk ved brug af webkomponenter med de populære JavaScript-rammer, du allerede kender og elsker.

Til det formål, lad os forbedre vores counter web-komponent en smule. Lad os få det til at acceptere en color attribut, for at kontrollere farven på den værdi, der vises. Og lad os også få det til at acceptere en increment ejendom, så forbrugere af denne webkomponent kan få den forøget med 2, 3, 4 ad gangen. Og for at drive disse tilstandsændringer, lad os bruge vores nye tæller i en Svelte-sandkasse - vi kommer til React om lidt.

Vi starter med den samme webkomponent som før og tilføjer en farveattribut. For at konfigurere vores webkomponent til at acceptere og reagere på en attribut, tilføjer vi en statisk observedAttributes egenskab, der returnerer de attributter, som vores webkomponent lytter efter.

static observedAttributes = ["color"];

Med det på plads kan vi tilføje en attributeChangedCallback livscyklusmetode, som vil køre, når nogen af ​​de attributter, der er angivet i observedAttributes er indstillet eller opdateret.

attributeChangedCallback(name, oldValue, newValue) { if (name === "color") { this.update(); }
}

Nu opdaterer vi vores update metode til faktisk at bruge det:

update() { this.valSpan.innerText = this._currentValue; this.valSpan.style.color = this.getAttribute("color") || "black";
}

Lad os endelig tilføje vores increment ejendom:

increment = 1;

Enkel og ydmyg.

Brug af tællerkomponenten i Svelte

Lad os bruge det, vi lige har lavet. Vi går ind i vores Svelte app-komponent og tilføjer noget som dette:

<script> let color = "red";
</script> <style> main { text-align: center; }
</style> <main> <select bind:value={color}> <option value="red">Red</option> <option value="green">Green</option> <option value="blue">Blue</option> </select> <counter-wc color={color}></counter-wc>
</main>

Og det virker! Vores tæller gengiver, øger, og rullemenuen opdaterer farven. Som du kan se, gengiver vi farveattributten i vores Svelte-skabelon, og når værdien ændres, håndterer Svelte opgaven med at kalde setAttribute på vores underliggende webkomponentinstans. Der er ikke noget særligt her: det er det samme, det allerede gør for egenskaberne enhver HTML element.

Tingene bliver lidt interessante med increment rekvisit. Dette er ikke en attribut på vores webkomponent; det er en rekvisit på webkomponentens klasse. Det betyder, at den skal indstilles på webkomponentens instans. Bær over med mig, da tingene ender meget enklere om lidt.

Først vil vi tilføje nogle variabler til vores Svelte-komponent:

let increment = 1;
let wcInstance;

Vores kraftcenter med en tællerkomponent vil lade dig øge med 1 eller 2:

<button on:click={() => increment = 1}>Increment 1</button>
<button on:click={() => increment = 2}>Increment 2</button>

Men, i teorien, skal vi have den faktiske forekomst af vores webkomponent. Dette er det samme, vi altid gør, når vi tilføjer en ref med React. Med Svelte er det enkelt bind:this direktiv:

<counter-wc bind:this={wcInstance} color={color}></counter-wc>

Nu, i vores Svelte-skabelon, lytter vi efter ændringer i vores komponents inkrementvariabel og indstiller den underliggende webkomponentegenskab.

$: { if (wcInstance) { wcInstance.increment = increment; }
}

Du kan teste det over på denne live demo.

Vi ønsker naturligvis ikke at gøre dette for hver webkomponent eller rekvisit, vi skal administrere. Ville det ikke være rart, hvis vi bare kunne indstille increment lige på vores webkomponent, i markup, som vi normalt gør for komponentrekvisitter, og har det, du ved, bare arbejde? Med andre ord ville det være rart, hvis vi kunne slette alle anvendelser af wcInstance og brug denne enklere kode i stedet:

<counter-wc increment={increment} color={color}></counter-wc>

Det viser sig, at vi kan. Denne kode virker; Svelte klarer alt det benarbejde for os. Tjek det ud i denne demo. Dette er standardadfærd for stort set alle JavaScript-rammer.

Så hvorfor viste jeg dig den manuelle måde at indstille webkomponentens prop på? To grunde: det er nyttigt at forstå, hvordan disse ting fungerer, og for et øjeblik siden sagde jeg, at dette virker for "stort set" alle JavaScript-rammer. Men der er et rammeværk, som skræmmende nok ikke understøtter indstilling af webkomponentprop, som vi lige har set.

React er et andet udyr

Opbygning af interoperable webkomponenter, der endda fungerer med React PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Opbygning af interoperable webkomponenter, der endda fungerer med React

Reagere. Den mest populære JavaScript-ramme på planeten understøtter ikke grundlæggende interop med webkomponenter. Dette er et velkendt problem, der er unikt for React. Interessant nok er dette faktisk rettet i Reacts eksperimentelle gren, men af ​​en eller anden grund blev det ikke slået sammen i version 18. Når det er sagt, kan vi stadig spore udviklingen af ​​det. Og du kan selv prøve dette med en live demo.

Løsningen er selvfølgelig at bruge en ref, tag fat i webkomponentforekomsten og indstil manuelt increment når denne værdi ændres. Det ser sådan ud:

import React, { useState, useRef, useEffect } from 'react';
import './counter-wc'; export default function App() { const [increment, setIncrement] = useState(1); const [color, setColor] = useState('red'); const wcRef = useRef(null); useEffect(() => { wcRef.current.increment = increment; }, [increment]); return ( <div> <div className="increment-container"> <button onClick={() => setIncrement(1)}>Increment by 1</button> <button onClick={() => setIncrement(2)}>Increment by 2</button> </div> <select value={color} onChange={(e) => setColor(e.target.value)}> <option value="red">Red</option> <option value="green">Green</option> <option value="blue">Blue</option> </select> <counter-wc ref={wcRef} increment={increment} color={color}></counter-wc> </div> );
}

Som vi diskuterede, er kodning af dette manuelt for hver webkomponentegenskab simpelthen ikke skalerbar. Men alt er ikke tabt, fordi vi har et par muligheder.

Mulighed 1: Brug attributter overalt

Vi har egenskaber. Hvis du klikkede på React-demoen ovenfor, increment prop virkede ikke, men farven blev ændret korrekt. Kan vi ikke kode alt med attributter? Desværre nej. Attributværdier kan kun være strenge. Det er godt nok her, og vi ville være i stand til at nå noget langt med denne tilgang. Tal som increment kan konverteres til og fra strenge. Vi kunne endda JSON stringify/parse objekter. Men til sidst bliver vi nødt til at overføre en funktion til en webkomponent, og på det tidspunkt ville vi være ude af muligheder.

Mulighed 2: Pak den ind

Der er et gammelt ordsprog, der siger, at du kan løse ethvert problem inden for datalogi ved at tilføje et niveau af indirekte (undtagen problemet med for mange niveauer af indirekte). Koden til at indstille disse rekvisitter er ret forudsigelig og enkel. Hvad hvis vi gemmer det i et bibliotek? De smarte folk bag Lit har én løsning. Dette bibliotek opretter en ny React-komponent til dig, efter du har givet den en webkomponent, og viser de egenskaber, den har brug for. Selvom jeg er klog, er jeg ikke fan af denne tilgang.

I stedet for at have en en-til-en kortlægning af webkomponenter til manuelt oprettede React-komponenter, foretrækker jeg bare en Reager komponent, at vi passerer vores web komponent tag navn til (counter-wc i vores tilfælde) – sammen med alle attributter og egenskaber – og for at denne komponent skal gengive vores webkomponent, skal du tilføje ref, så find ud af, hvad der er en rekvisit, og hvad der er en egenskab. Det er den ideelle løsning efter min mening. Jeg kender ikke et bibliotek, der gør dette, men det burde være ligetil at oprette. Lad os give det et skud!

Dette er den forbrug vi leder efter:

<WcWrapper wcTag="counter-wc" increment={increment} color={color} />

wcTag er webkomponentens tagnavn; resten er de egenskaber og egenskaber, vi ønsker videregivet.

Sådan ser min implementering ud:

import React, { createElement, useRef, useLayoutEffect, memo } from 'react'; const _WcWrapper = (props) => { const { wcTag, children, ...restProps } = props; const wcRef = useRef(null); useLayoutEffect(() => { const wc = wcRef.current; for (const [key, value] of Object.entries(restProps)) { if (key in wc) { if (wc[key] !== value) { wc[key] = value; } } else { if (wc.getAttribute(key) !== value) { wc.setAttribute(key, value); } } } }); return createElement(wcTag, { ref: wcRef });
}; export const WcWrapper = memo(_WcWrapper);

Den mest interessante linje er til sidst:

return createElement(wcTag, { ref: wcRef });

Sådan laver vi et element i React med et dynamisk navn. Faktisk er det dette, som React normalt transpilerer JSX til. Alle vores divs er konverteret til createElement("div") opkald. Vi behøver normalt ikke at kalde denne API direkte, men den er der, når vi har brug for den.

Ud over det ønsker vi at køre en layout-effekt og gennemgå hver rekvisit, som vi har videregivet til vores komponent. Vi går igennem dem alle og tjekker, om det er en ejendom med en in check, der kontrollerer webkomponentforekomstobjektet såvel som dets prototypekæde, som vil fange eventuelle gettere/settere, der ender på klasseprototypen. Hvis der ikke findes en sådan egenskab, antages det at være en attribut. I begge tilfælde indstiller vi det kun, hvis værdien faktisk har ændret sig.

Hvis du undrer dig over, hvorfor vi bruger useLayoutEffect i stedet for useEffect, det er fordi vi ønsker at køre disse opdateringer med det samme, før vores indhold gengives. Bemærk også, at vi ikke har noget afhængighedsarray til vores useLayoutEffect; det betyder, at vi ønsker at køre denne opdatering på hver gengivelse. Dette kan være risikabelt, da React har en tendens til at gengive en masse. Jeg forbedrer dette ved at pakke det hele ind React.memo. Dette er i bund og grund den moderne version af React.PureComponent, hvilket betyder, at komponenten kun gengengives, hvis nogen af ​​dens faktiske rekvisitter er ændret - og den kontrollerer, om det er sket via en simpel lighedskontrol.

Den eneste risiko her er, at hvis du sender en objektrekvisit, som du muterer direkte uden at gentildele, så vil du ikke se opdateringerne. Men dette frarådes stærkt, især i React-samfundet, så jeg ville ikke bekymre mig om det.

Inden jeg går videre, vil jeg gerne sige en sidste ting. Du er måske ikke tilfreds med, hvordan brugen ser ud. Igen bruges denne komponent sådan:

<WcWrapper wcTag="counter-wc" increment={increment} color={color} />

Specifikt kan du måske ikke lide at videregive webkomponent-tagnavnet til <WcWrapper> komponent og foretrækker i stedet @lit-labs/react pakken ovenfor, som opretter en ny individuel React-komponent for hver webkomponent. Det er helt fair, og jeg vil opfordre dig til at bruge det, du er mest komfortabel med. Men for mig er en fordel ved denne tilgang, at det er nemt at slette. Hvis React ved et mirakel fusionerer korrekt webkomponenthåndtering fra deres eksperimentelle gren til main i morgen vil du være i stand til at ændre ovenstående kode fra dette:

<WcWrapper wcTag="counter-wc" increment={increment} color={color} />

…Til dette:

<counter-wc ref={wcRef} increment={increment} color={color} />

Du kunne sikkert endda skrive en enkelt kodemod til at gøre det overalt og derefter slette <WcWrapper> i det hele taget. Faktisk, rids det: en global søgning og erstat med en RegEx ville sandsynligvis fungere.

Implementeringen

Jeg ved godt, det ser ud til, at det tog en rejse at komme hertil. Hvis du husker det, var vores oprindelige mål at tage den billedeksempelkode, vi så på i min lastning indlæg, og flyt den til en webkomponent, så den kan bruges i enhver JavaScript-ramme. Reacts mangel på ordentlig interop tilføjede en masse detaljer til blandingen. Men nu hvor vi har et ordentligt greb om, hvordan man opretter en webkomponent og bruger den, vil implementeringen nærmest være anti-klimaktisk.

Jeg dropper hele webkomponenten her og kalder nogle af de interessante ting frem. Hvis du gerne vil se den i aktion, er her en fungerende demo. Det vil skifte mellem mine tre yndlingsbøger på mine tre yndlingsprogrammeringssprog. URL'en for hver bog vil være unik hver gang, så du kan se forhåndsvisningen, selvom du sandsynligvis vil skrue ned for tingene på din DevTools Network-fane for virkelig at se, hvad der foregår.

Se hele koden
class BookCover extends HTMLElement { static observedAttributes = ['url']; attributeChangedCallback(name, oldValue, newValue) { if (name === 'url') { this.createMainImage(newValue); } } set preview(val) { this.previewEl = this.createPreview(val); this.render(); } createPreview(val) { if (typeof val === 'string') { return base64Preview(val); } else { return blurHashPreview(val); } } createMainImage(url) { this.loaded = false; const img = document.createElement('img'); img.alt = 'Book cover'; img.addEventListener('load', () =&gt; { if (img === this.imageEl) { this.loaded = true; this.render(); } }); img.src = url; this.imageEl = img; } connectedCallback() { this.render(); } render() { const elementMaybe = this.loaded ? this.imageEl : this.previewEl; syncSingleChild(this, elementMaybe); }
}

Først registrerer vi den egenskab, vi er interesseret i, og reagerer, når den ændres:

static observedAttributes = ['url']; attributeChangedCallback(name, oldValue, newValue) { if (name === 'url') { this.createMainImage(newValue); }
}

Dette får vores billedkomponent til at blive oprettet, som kun vises, når den er indlæst:

createMainImage(url) { this.loaded = false; const img = document.createElement('img'); img.alt = 'Book cover'; img.addEventListener('load', () => { if (img === this.imageEl) { this.loaded = true; this.render(); } }); img.src = url; this.imageEl = img;
}

Dernæst har vi vores preview-egenskab, som enten kan være vores base64 preview-streng eller vores blurhash pakke:

set preview(val) { this.previewEl = this.createPreview(val); this.render();
} createPreview(val) { if (typeof val === 'string') { return base64Preview(val); } else { return blurHashPreview(val); }
}

Dette afhænger af, hvilken hjælperfunktion vi har brug for:

function base64Preview(val) { const img = document.createElement('img'); img.src = val; return img;
} function blurHashPreview(preview) { const canvasEl = document.createElement('canvas'); const { w: width, h: height } = preview; canvasEl.width = width; canvasEl.height = height; const pixels = decode(preview.blurhash, width, height); const ctx = canvasEl.getContext('2d'); const imageData = ctx.createImageData(width, height); imageData.data.set(pixels); ctx.putImageData(imageData, 0, 0); return canvasEl;
}

Og til sidst vores render metode:

connectedCallback() { this.render();
} render() { const elementMaybe = this.loaded ? this.imageEl : this.previewEl; syncSingleChild(this, elementMaybe);
}

Og et par hjælpermetoder til at binde alt sammen:

export function syncSingleChild(container, child) { const currentChild = container.firstElementChild; if (currentChild !== child) { clearContainer(container); if (child) { container.appendChild(child); } }
} export function clearContainer(el) { let child; while ((child = el.firstElementChild)) { el.removeChild(child); }
}

Det er en lille smule mere kedelplade, end vi ville have brug for, hvis vi bygger dette i en ramme, men fordelen er, at vi kan genbruge dette i enhver ramme, vi ønsker - selvom React har brug for en indpakning for nu, som vi diskuterede .

Odds og slutter

Jeg har allerede nævnt Lit's React-indpakning. Men hvis du finder dig selv at bruge Stencil, understøtter det faktisk en separat output pipeline kun til React. Og det har de gode folk hos Microsoft også skabt noget, der ligner Lits indpakning, knyttet til Fast web-komponentbiblioteket.

Som jeg nævnte, vil alle frameworks, der ikke hedder React, håndtere indstilling af webkomponentegenskaber for dig. Bare bemærk, at nogle har nogle specielle smagsvarianter af syntaks. For eksempel med Solid.js, <your-wc value={12}> går altid ud fra det value er en ejendom, som du kan tilsidesætte med en attr præfiks, som <your-wc attr:value={12}>.

Indpakning op

Webkomponenter er en interessant, ofte underudnyttet del af webudviklingslandskabet. De kan hjælpe med at reducere din afhængighed af en enkelt JavaScript-ramme ved at administrere din brugergrænseflade eller "blade"-komponenter. Selvom at skabe disse som webkomponenter - i modsætning til Svelte- eller React-komponenter - ikke vil være så ergonomisk, er fordelen, at de i vid udstrækning kan genbruges.


Opbygning af interoperable webkomponenter, der endda fungerer med React oprindeligt udgivet den CSS-tricks. Du burde få nyhedsbrevet.

Tidsstempel:

Mere fra CSS-tricks