Együttműködő webkomponensek létrehozása, amelyek még a React PlatoBlockchain adatintelligenciával is működnek. Függőleges keresés. Ai.

Együttműködő webkomponensek létrehozása, amelyek még a React-tal is működnek

Azok közülünk, akik több mint néhány éve webfejlesztők vagyunk, valószínűleg több JavaScript-keretrendszer használatával írtunk kódot. Az összes választási lehetőség mellett – React, Svelte, Vue, Angular, Solid – mindez elkerülhetetlen. Az egyik leginkább frusztráló dolog, amellyel a keretrendszereken átívelő munka során meg kell küzdenünk, hogy újra létrehozzuk az összes alacsony szintű felhasználói felület-összetevőt: gombokat, lapokat, legördülő listákat stb. Ami különösen frusztráló, hogy általában egy keretrendszerben határozzuk meg őket. , mondjuk a React, de aztán át kell írni őket, ha valamit fel akarunk építeni a Svelte-ben. Vagy Vue. Vagy Szilárd. Stb.

Nem lenne jobb, ha egyszer, keretrendszer-agnosztikus módon definiálhatnánk ezeket az alacsony szintű felhasználói felület összetevőket, majd újra felhasználnánk őket a keretrendszerek között? Persze hogy lenne! És megtehetjük; webkomponensek jelentik az utat. Ez a bejegyzés megmutatja, hogyan.

Jelenleg a webes összetevők SSR sztorija egy kicsit hiányzik. A deklaratív árnyék-DOM (DSD) a webkomponensek szerveroldali megjelenítése, de jelen pillanatban nem integrálták kedvenc alkalmazási keretrendszereivel, mint például a Next, a Remix vagy a SvelteKit. Ha ez kötelező, ellenőrizze a DSD legújabb állapotát. De egyébként, ha nem az SSR-t használod, olvass tovább.

Először is egy kis kontextus

A webkomponensek alapvetően olyan HTML elemek, amelyeket Ön határoz meg, például <yummy-pizza> vagy bármi, az alapoktól kezdve. Itt, a CSS-Tricks-en mindenhol le van fedve (beleértve Caleb Williams kiterjedt sorozata és a az egyiket John Rhea készítette), de röviden végigjárjuk a folyamatot. Lényegében meg kell határoznia egy JavaScript osztályt, és örökölnie kell HTMLElement, majd meghatározza a webkomponens tulajdonságait, attribútumait és stílusait, és természetesen a jelölést, amelyet végül megjelenít a felhasználók számára.

Izgalmas, hogy olyan egyéni HTML-elemeket definiálhatunk, amelyek nem kapcsolódnak egyetlen összetevőhöz sem. De ez a szabadság egyben korlát is. Bármely JavaScript-keretrendszertől függetlenül létezik, azt jelenti, hogy nem tud igazán együttműködni ezekkel a JavaScript-keretrendszerekkel. Gondoljon egy React komponensre, amely lekér néhány adatot, majd megjelenít néhányat egyéb React komponens, továbbítja az adatokat. Ez nem igazán működne webkomponensként, mivel a webes összetevő nem tudja, hogyan kell megjeleníteni egy React összetevőt.

A webkomponensek különösen kiválóak levél összetevői. A levél összetevői az utolsó dolog, amelyet az összetevőfában kell megjeleníteni. Ezek azok a komponensek, amelyek bizonyos kellékeket kapnak, és néhányat leképeznek UI. Ezek nem az összetevőfa közepén ülő, adattovábbítás, kontextus beállítása stb. UI ugyanúgy fog kinézni, függetlenül attól, hogy melyik JavaScript-keretrendszer működteti az alkalmazás többi részét.

Az általunk épített webkomponens

Ahelyett, hogy valami unalmast (és általánosat), például egy gombot építsünk, építsünk valami mást. Az én Utolsó poszt Megvizsgáltuk az elmosódott kép-előnézetek használatát, hogy megakadályozzuk a tartalom újrafolyamatát, és megfelelő felhasználói felületet biztosítsunk a képek betöltése közben. Megnéztük a base64-et, amely képeink homályos, degradált verzióit kódolta, és megmutatta ezt a felhasználói felületünkön, miközben a valódi kép betöltődött. Megvizsgáltuk azt is, hogyan hozhatunk létre hihetetlenül kompakt, elmosódott előnézeteket az ún Blurhash.

Ez a bejegyzés megmutatta, hogyan hozhatja létre ezeket az előnézeteket, és hogyan használhatja őket egy React projektben. Ez a bejegyzés megmutatja, hogyan használhatja ezeket az előnézeteket a webes összetevőkből, hogy használhassák őket bármilyen JavaScript keretrendszer.

De sétálnunk kell, mielőtt futhatnánk, ezért először végigmegyünk valami triviális és buta dolgot, hogy pontosan lássuk, hogyan működnek a webes összetevők.

Ebben a bejegyzésben minden szerszám nélkül vanília webkomponenseket épít fel. Ez azt jelenti, hogy a kódnak lesz egy kis alaprajza, de viszonylag könnyen követhetőnek kell lennie. Olyan eszközök, mint Megvilágított or Stencil webelemek építésére tervezték, és a kazánlemez nagy részének eltávolítására használhatók. Arra kérlek, hogy nézd meg őket! De ehhez a poszthoz inkább egy kicsit több kazánt választok, cserébe azért, hogy ne kelljen újabb függőséget bevezetnem és tanítanom.

Egy egyszerű számláló alkatrész

Építsük meg a JavaScript összetevők klasszikus „Hello World”-ét: egy számlálót. Megjelenítünk egy értéket, és egy gombot, amely növeli az értéket. Egyszerű és unalmas, de a lehető legegyszerűbb webkomponenst nézzük meg.

Egy webes komponens felépítéséhez az első lépés egy JavaScript osztály létrehozása, amely örököl HTMLElement:

class Counter extends HTMLElement {}

Az utolsó lépés a webkomponens regisztrálása, de csak akkor, ha még nem regisztráltuk:

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

És természetesen jelenítse meg:

<counter-wc></counter-wc>

És minden, ami a kettő között van, az, hogy a webkomponenst azt csinálja, amit csak akarunk. Az egyik általános életciklus-módszer az connectedCallback, amely akkor indul el, amikor a webkomponensünket hozzáadjuk a DOM-hoz. Ezt a módszert bármilyen tartalom megjelenítésére használhatjuk. Ne feledje, ez egy JS osztály, amely innen öröklődik HTMLElement, ami a miénket jelenti this Az érték maga a webkomponens elem, az összes szokásos DOM-manipulációs módszerrel, amelyet már ismer és szeret.

A legegyszerűbb esetben ezt tehetjük:

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

…ami jól fog működni.

A "hé" szó zöld színben.
Együttműködő webkomponensek létrehozása, amelyek még a React-tal is működnek

Valódi tartalom hozzáadása

Adjunk hozzá néhány hasznos, interaktív tartalmat. Szükségünk van egy <span> az aktuális számérték megtartásához és a <button> hogy növelje a számlálót. Egyelőre létrehozzuk ezt a tartalmat a konstruktorunkban, és hozzáfűzzük, amikor a webes összetevő ténylegesen a DOM-ban van:

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();
}

Ha nagyon elnagyolta a kézi DOM-létrehozás, ne feledje, hogy beállíthatja innerHTML, vagy akár egyszer létrehozhat egy sablonelemet a webkomponens osztály statikus tulajdonságaként, klónozhatja, és beillesztheti az új webkomponens-példányok tartalmát. Valószínűleg van néhány más lehetőség is, amelyekre nem gondolok, vagy mindig használhatsz webkomponens-keretrendszert, mint pl Megvilágított or Stencil. De ennél a bejegyzésnél továbbra is az egyszerűségre törekszünk.

Továbblépve szükségünk van egy beállítható JavaScript osztály tulajdonságra value

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

Ez csak egy standard osztálytulajdonság egy setterrel, valamint egy második tulajdonság az érték megtartására. Az egyik szórakoztató csavar az, hogy ezekhez az értékekhez a privát JavaScript osztály tulajdonság szintaxisát használom. Ez azt jelenti, hogy a webes összetevőn kívül senki sem érintheti meg ezeket az értékeket. Ez a szabványos JavaScript ezt minden modern böngésző támogatja, ezért ne féljen használni.

Vagy hívj bátran _value ha jobban tetszik. És végül a miénk update eljárás:

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

Működik!

A számláló web komponens.
Együttműködő webkomponensek létrehozása, amelyek még a React-tal is működnek

Nyilvánvaló, hogy ezt a kódot nem szeretné nagy méretben karbantartani. Itt egy teljes működő példa ha szeretnéd közelebbről megnézni. Mint mondtam, az olyan eszközöket, mint a Lit és a Stencil, úgy tervezték, hogy ezt egyszerűbbé tegyék.

További funkciók hozzáadása

Ez a bejegyzés nem a webes összetevők mélyére merül. Nem fedjük le az összes API-t és életciklust; nem is fedezzük árnyékgyökerek vagy rések. Végtelen tartalom van ezekben a témákban. Célom itt az, hogy egy tisztességes bevezetést nyújtsak az érdeklődés felkeltéséhez, valamint néhány hasznos útmutatást a valóságról segítségével webkomponensek a már ismert és kedvelt JavaScript-keretrendszerekkel.

Ennek érdekében javítsuk egy kicsit a számlálóweb komponensünket. Fogadjuk el a color attribútum segítségével szabályozhatja a megjelenített érték színét. És azt is fogadjuk el an increment tulajdonságot, így ennek a webkomponensnek a fogyasztói egyszerre 2, 3, 4-gyel növelhetik. És hogy ezeket az állapotváltozásokat előmozdítsuk, használjuk az új számlálónkat egy Svelte homokozóban – rövid időn belül eljutunk a React-hez.

Ugyanazzal a webes összetevővel kezdjük, mint korábban, és hozzáadunk egy színattribútumot. Ahhoz, hogy webösszetevőnket úgy konfigurálhassuk, hogy egy attribútumot fogadjon el és válaszoljon rá, hozzáadunk egy statikus értéket observedAttributes tulajdonság, amely visszaadja azokat az attribútumokat, amelyekre webösszetevőnk figyel.

static observedAttributes = ["color"];

Ezzel a helyén hozzáadhatjuk a attributeChangedCallback életciklus-módszer, amely akkor fut le, amikor a felsorolt ​​attribútumok bármelyike ​​megjelenik observedAttributes be vannak állítva vagy frissítve.

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

Most frissítjük update a tényleges használat módja:

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

Végül tegyük hozzá a sajátunkat increment ingatlan:

increment = 1;

Egyszerű és alázatos.

A számláló komponens használata a Svelte-ben

Használjuk, amit most készítettünk. Bemegyünk a Svelte alkalmazás összetevőjébe, és hozzáadunk valami ehhez hasonlót:

<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>

És működik! A számláló megjeleníti, növeli, és a legördülő menü frissíti a színt. Amint láthatja, a color attribútumot a Svelte sablonunkban jelenítjük meg, és ha az érték megváltozik, a Svelte kezeli a hívás lábmunkáját. setAttribute az alapul szolgáló webkomponens-példányunkon. Nincs itt semmi különös: ez ugyanaz, mint a tulajdonságok esetében bármilyen HTML elem.

A dolgok egy kicsit érdekessé válnak a increment támaszt. Ez nem attribútum a webkomponensünkön; ez egy kellék a webkomponens osztályában. Ez azt jelenti, hogy be kell állítani a webes összetevő példányán. Tarts ki velem, mert a dolgok egy kicsit sokkal egyszerűbbé válnak.

Először is hozzáadunk néhány változót a Svelte komponensünkhöz:

let increment = 1;
let wcInstance;

A számlálókomponensből álló erőgépünk lehetővé teszi, hogy 1-gyel vagy 2-vel növelje:

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

De, elméletben, meg kell szereznünk a webkomponensünk tényleges példányát. Ez ugyanaz, amit mindig csinálunk, amikor hozzáadjuk a ref a React segítségével. A Svelte esetében ez egyszerű bind:this irányelv:

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

Most a Svelte sablonunkban figyeljük az összetevő növekményi változójának változásait, és beállítjuk az alapul szolgáló webkomponens tulajdonságot.

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

Ki lehet próbálni ezen az élő bemutatón.

Nyilvánvalóan nem akarjuk ezt megtenni minden webkomponens vagy kellék esetében, amelyet kezelnünk kell. Nem lenne jó, ha beállíthatnánk increment közvetlenül a webes komponensünkön, a jelölésben, ahogyan általában az összetevők kellékeinél tesszük, és ez, tudod, csak munka? Más szóval, jó lenne, ha törölnénk az összes használatot wcInstance és használja helyette ezt az egyszerűbb kódot:

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

Kiderült, hogy képesek vagyunk rá. Ez a kód működik; A Svelte mindezt a lábmunkát megoldja helyettünk. Tekintse meg ebben a demóban. Ez nagyjából az összes JavaScript-keretrendszer szokásos viselkedése.

Akkor miért mutattam meg a webkomponens támaszának manuális beállítását? Két ok: hasznos megérteni, hogyan működnek ezek a dolgok, és egy pillanattal ezelőtt azt mondtam, hogy ez „nagyjából” az összes JavaScript-keretrendszeren működik. De van egy keretrendszer, amely őrjítő módon nem támogatja a webkomponensek beállítását, ahogyan azt az imént láttuk.

A React egy másik vadállat

Együttműködő webkomponensek létrehozása, amelyek még a React PlatoBlockchain adatintelligenciával is működnek. Függőleges keresés. Ai.
Együttműködő webkomponensek létrehozása, amelyek még a React-tal is működnek

Reagál. A bolygó legnépszerűbb JavaScript-keretrendszere nem támogatja az alapvető együttműködést a webes összetevőkkel. Ez egy jól ismert probléma, amely egyedülálló a React esetében. Érdekes módon ez a React kísérleti ágában valóban meg van javítva, de valamiért nem egyesítették a 18-as verzióval. nyomon követni annak előrehaladását. És ezt magad is kipróbálhatod a élő demo.

A megoldás természetesen az a ref, fogja meg a webösszetevő példányát, és állítsa be kézzel increment amikor ez az érték megváltozik. Ez így néz ki:

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> );
}

Amint azt már megbeszéltük, ennek manuális kódolása minden webkomponens-tulajdonhoz egyszerűen nem méretezhető. De nincs minden veszve, mert van néhány lehetőségünk.

1. lehetőség: Attribútumok használata mindenhol

Vannak tulajdonságaink. Ha a fenti React bemutatóra kattintott, a increment A prop nem működött, de a szín megfelelően megváltozott. Nem kódolhatunk mindent attribútumokkal? Sajnos nem. Az attribútumértékek csak karakterláncok lehetnek. Ez itt elég jó, és ezzel a megközelítéssel valamennyire messzire jutnánk. Számok, mint increment karakterláncokká és karakterláncokból konvertálható. Akár a JSON-ban is stringizálhatnánk/elemezhetnénk az objektumokat. De végül át kell adnunk egy függvényt egy webes komponensbe, és akkor kifogynánk a lehetőségekből.

2. lehetőség: csomagolja be

Van egy régi mondás, miszerint az informatika bármely problémáját megoldhatja az indirektség szintjének hozzáadásával (kivéve a túl sok indirektségi szint problémáját). A kellékek beállításához szükséges kód meglehetősen kiszámítható és egyszerű. Mi van, ha egy könyvtárban rejtjük el? Az okos emberek Lit mögött van egy megoldás. Ez a könyvtár létrehoz egy új React összetevőt, miután adott neki egy webes összetevőt, és felsorolja a szükséges tulajdonságokat. Bár okos vagyok, nem vagyok híve ennek a megközelítésnek.

Ahelyett, hogy a webes összetevőket egy-egy leképezéssel hozzárendelném a manuálisan létrehozott React-komponensekhez, inkább csak egy Reagálja a komponenst, hogy átadjuk a webkomponensünket címke neve nak nek (counter-wc esetünkben) – az összes attribútummal és tulajdonsággal együtt –, és ahhoz, hogy ez a komponens megjelenítse a webkomponensünket, adja hozzá a ref, akkor derítsd ki, mi a kellék és mi az attribútum. Ez az ideális megoldás szerintem. Nem ismerek olyan könyvtárat, amely ezt csinálja, de egyszerűnek kell lennie létrehozni. Tegyünk egy próbát!

Ez a használat keresünk:

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

wcTag a webkomponens címke neve; a többi azok a tulajdonságok és attribútumok, amelyeket tovább akarunk adni.

Így néz ki a megvalósításom:

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);

A legérdekesebb sor a végén található:

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

Így hozunk létre egy elemet a Reactban dinamikus névvel. Valójában a React általában erre fordítja át a JSX-et. Minden divünk konvertálva van createElement("div") hívásokat. Általában nem kell közvetlenül meghívnunk ezt az API-t, de ott van, amikor szükségünk van rá.

Ezen túlmenően szeretnénk egy elrendezési effektust futtatni, és minden olyan kelléken keresztül kell menni, amelyet átadtunk a komponensünknek. Végignézzük az összeset, és megnézzük, hogy egy ingatlanról van-e szó in ellenőrizze, hogy ellenőrzi a webkomponens-példányobjektumot, valamint annak prototípus-láncát, amely elkapja az osztály prototípusára feltörő gettereket/settereket. Ha nem létezik ilyen tulajdonság, akkor azt attribútumnak kell tekinteni. Mindkét esetben csak akkor állítjuk be, ha az érték valóban megváltozott.

Ha kíváncsi, miért használjuk useLayoutEffect helyett useEffect, ez azért van, mert azonnal le akarjuk futtatni ezeket a frissítéseket, mielőtt a tartalom megjelenne. Azt is vegye figyelembe, hogy nincs függőségi tömbünk useLayoutEffect; ez azt jelenti, hogy ezen a frissítésen szeretnénk futni minden render. Ez kockázatos lehet, mivel a React hajlamos újrarenderelni nagyon. Ezt úgy javítom, hogy az egészet becsomagolom React.memo. Ez lényegében a modern változata React.PureComponent, ami azt jelenti, hogy a komponens csak akkor jelenik meg újra, ha a tényleges kellékei megváltoztak – és egy egyszerű egyenlőség-ellenőrzéssel ellenőrzi, hogy ez megtörtént-e.

Az egyetlen kockázat itt az, hogy ha olyan objektum-támaszt ad át, amelyet közvetlenül mutál, anélkül, hogy újra hozzárendelné, akkor nem fogja látni a frissítéseket. De ez nagyon elkeseredett, különösen a React közösségben, ezért nem aggódnék miatta.

Mielőtt továbblépnék, még egy utolsó dolgot szeretnék kiemelni. Lehet, hogy nem elégedett a használat kinézetével. Ezt az összetevőt ismét a következőképpen használják:

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

Konkrétan előfordulhat, hogy nem szeretné átadni a webkomponens címke nevét a <WcWrapper> komponenst, és inkább a @lit-labs/react fenti csomagot, amely minden webkomponenshez új egyedi React összetevőt hoz létre. Ez teljesen tisztességes, és arra biztatlak, hogy azt használd, amiben a legkényelmesebb. Számomra azonban ennek a megközelítésnek az egyik előnye, hogy könnyű töröl. Ha valami csoda folytán a React a megfelelő webkomponens kezelést egyesíti kísérleti ágából main holnap módosíthatja a fenti kódot erről:

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

…ehhez:

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

Valószínűleg akár egyetlen codemodet is írhatna, hogy ezt mindenhol elvégezze, majd törölje <WcWrapper> teljesen. Valójában törölje le: a globális keresés és a reguláris kifejezésre való lecserélése valószínűleg működne.

Az implementáció

Tudom, úgy tűnik, egy utazásba telt eljutni idáig. Ha emlékszel, eredeti célunk az volt, hogy elkészítsük a kép előnézeti kódját, amit a sajátomban megnéztünk Utolsó poszt, és helyezze át egy webkomponensbe, így bármilyen JavaScript-keretrendszerben használható. A React megfelelő együttműködésének hiánya sok részletet adott a keverékhez. De most, hogy tisztességes fogantyúval rendelkezünk a webkomponens létrehozásához és használatához, a megvalósítás szinte anti-klimatikus lesz.

Bedobom a teljes webes komponenst, és kiemelek néhány érdekességet. Ha szeretnéd működés közben látni, itt van a működő demo. Váltogatni fog a három kedvenc könyvem között a három kedvenc programozási nyelvemen. Az egyes könyvek URL-címe minden alkalommal egyedi lesz, így láthatja az előnézetet, bár valószínűleg a DevTools Network lapon kell szabályoznia a dolgokat, hogy valóban láthassa a dolgok történését.

A teljes kód megtekintése
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); }
}

Először regisztráljuk a minket érdeklő attribútumot, és reagálunk, ha megváltozik:

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

Emiatt létrejön a képösszetevőnk, amely csak betöltéskor jelenik meg:

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;
}

Ezután megkapjuk az előnézeti tulajdonságunkat, amely lehet a base64 előnézeti karakterláncunk, vagy a miénk blurhash csomag:

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

Ez elhalasztja a szükséges segédfunkciókat:

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;
}

És végül a miénk render eljárás:

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

És néhány segédmódszer, amellyel mindent össze lehet kötni:

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); }
}

Kicsit több mint amennyire szükségünk lenne, ha ezt keretrendszerben építjük meg, de az előnye az, hogy bármilyen keretrendszerben újra felhasználhatjuk – bár a Reactnak egyelőre szüksége lesz egy burkolóanyagra, ahogy megbeszéltük. .

Limlom

Már említettem Lit React burkolóját. De ha úgy találja, hogy Stencilt használ, az valójában támogatja a külön kimeneti csővezeték csak a React számára. És a Microsoft jó emberei is valami hasonlót készített Lit wrapperjéhez, csatolva a Fast web összetevő könyvtárához.

Mint említettem, minden, nem React nevű keretrendszer kezeli a webes összetevők tulajdonságainak beállítását. Csak vegye figyelembe, hogy némelyiknek van néhány különleges szintaxisa. Például a Solid.js használatával <your-wc value={12}> mindig ezt feltételezi value egy tulajdonság, amelyet felülbírálhat egy attr előtag, mint <your-wc attr:value={12}>.

Csomagolta

A webes összetevők a webfejlesztési környezet érdekes, gyakran alulhasznált részét képezik. Segíthetnek csökkenteni a függőséget bármely JavaScript-keretrendszertől a felhasználói felület vagy a „levél” összetevők kezelésével. Miközben ezeket webes komponensként hozzuk létre – ellentétben a Svelte vagy React komponensekkel – nem lesz olyan ergonomikus, az előnye, hogy széles körben újrafelhasználhatóak lesznek.


Együttműködő webkomponensek létrehozása, amelyek még a React-tal is működnek eredetileg megjelent CSS-trükkök. Neked kellene kapja meg a hírlevelet.

Időbélyeg:

Még több CSS trükkök