Membangun Komponen Web yang Dapat Dioperasikan Yang Bahkan Bekerja Dengan React PlatoBlockchain Data Intelligence. Pencarian Vertikal. ai.

Membangun Komponen Web Interoperable Yang Bahkan Bekerja Dengan React

Kita yang telah menjadi pengembang web lebih dari beberapa tahun mungkin pernah menulis kode menggunakan lebih dari satu kerangka kerja JavaScript. Dengan semua pilihan di luar sana โ€” React, Svelte, Vue, Angular, Solid โ€” semuanya tak terelakkan. Salah satu hal yang lebih membuat frustrasi yang harus kami tangani saat bekerja lintas kerangka kerja adalah membuat ulang semua komponen UI tingkat rendah itu: tombol, tab, tarik-turun, dll. Yang paling membuat frustrasi adalah kami biasanya mendefinisikannya dalam satu kerangka kerja. , katakan React, tetapi kemudian perlu menulis ulang jika kita ingin membangun sesuatu di Svelte. Atau Vue. Atau Padat. Dan seterusnya.

Bukankah lebih baik jika kita bisa mendefinisikan komponen UI tingkat rendah ini sekali, dengan cara kerangka-agnostik, dan kemudian menggunakannya kembali di antara kerangka kerja? Tentu saja! Dan kita bisa; komponen web adalah caranya. Posting ini akan menunjukkan caranya.

Sampai sekarang, cerita SSR untuk komponen web agak kurang. Shadow DOM (DSD) deklaratif adalah cara komponen web dirender di sisi server, tetapi, pada saat penulisan ini, komponen tersebut tidak terintegrasi dengan kerangka kerja aplikasi favorit Anda seperti Berikutnya, Remix, atau SvelteKit. Jika itu persyaratan untuk Anda, pastikan untuk memeriksa status terbaru DSD. Tetapi sebaliknya, jika SSR bukan sesuatu yang Anda gunakan, baca terus.

Pertama, beberapa konteks

Komponen Web pada dasarnya adalah elemen HTML yang Anda definisikan sendiri, seperti <yummy-pizza> atau apa pun, dari bawah ke atas. Semuanya dibahas di sini di CSS-Tricks (termasuk seri ekstensif oleh Caleb Williams dan satu oleh John Rhea) tetapi kita akan membahas prosesnya secara singkat. Pada dasarnya, Anda mendefinisikan kelas JavaScript, mewarisinya dari HTMLElement, lalu tentukan properti, atribut, dan gaya apa pun yang dimiliki komponen web dan, tentu saja, markup yang pada akhirnya akan dirender ke pengguna Anda.

Mampu mendefinisikan elemen HTML khusus yang tidak terikat pada komponen tertentu sangat menarik. Tetapi kebebasan ini juga merupakan batasan. Ada secara independen dari kerangka kerja JavaScript apa pun berarti Anda tidak dapat benar-benar berinteraksi dengan kerangka kerja JavaScript tersebut. Pikirkan komponen React yang mengambil beberapa data dan kemudian merender beberapa lain React komponen, meneruskan data. Ini tidak akan benar-benar berfungsi sebagai komponen web, karena komponen web tidak tahu cara merender komponen React.

Komponen web sangat unggul sebagai komponen daun. komponen daun adalah hal terakhir yang dirender di pohon komponen. Ini adalah komponen yang menerima beberapa alat peraga, dan membuat beberapa UI. Ini adalah tidak komponen yang berada di tengah-tengah pohon komponen Anda, meneruskan data, mengatur konteks, dll. โ€” hanya bagian murni dari UI itu akan terlihat sama, apa pun kerangka kerja JavaScript yang mendukung aplikasi lainnya.

Komponen web yang kami buat

Daripada membangun sesuatu yang membosankan (dan umum), seperti tombol, mari kita buat sesuatu yang sedikit berbeda. di my memuat posting kami melihat menggunakan pratinjau gambar buram untuk mencegah aliran ulang konten, dan memberikan UI yang layak bagi pengguna saat gambar kami dimuat. Kami melihat base64 menyandikan versi gambar kami yang buram dan terdegradasi, dan menunjukkannya di UI kami saat gambar asli dimuat. Kami juga melihat untuk menghasilkan pratinjau yang sangat ringkas dan buram menggunakan alat yang disebut blurhash.

Posting itu menunjukkan kepada Anda cara membuat pratinjau itu dan menggunakannya dalam proyek React. Posting ini akan menunjukkan cara menggunakan pratinjau tersebut dari komponen web sehingga dapat digunakan oleh Apa pun kerangka kerja JavaScript.

Tapi kita perlu berjalan sebelum kita bisa berlari, jadi kita akan melewati sesuatu yang sepele dan konyol terlebih dahulu untuk melihat dengan tepat bagaimana komponen web bekerja.

Semua yang ada di postingan ini akan membuat komponen web vanilla tanpa alat apa pun. Itu berarti kode akan memiliki sedikit boilerplate, tetapi harus relatif mudah diikuti. Alat seperti Lit or Setensilan dirancang untuk membuat komponen web dan dapat digunakan untuk membuang sebagian besar pelat ketel ini. Saya mendorong Anda untuk memeriksanya! Tetapi untuk posting ini, saya akan lebih suka sedikit boilerplate sebagai ganti tidak harus memperkenalkan dan mengajarkan ketergantungan lain.

Komponen penghitung sederhana

Mari kita buat komponen JavaScript "Hello World" klasik: penghitung. Kami akan membuat nilai, dan tombol yang menambah nilai itu. Sederhana dan membosankan, tetapi ini akan membuat kita melihat komponen web yang paling sederhana.

Untuk membangun komponen web, langkah pertama adalah membuat kelas JavaScript, yang mewarisi dari HTMLElement:

class Counter extends HTMLElement {}

Langkah terakhir adalah mendaftarkan komponen web, tetapi hanya jika kita belum mendaftarkannya:

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

Dan, tentu saja, buat:

<counter-wc></counter-wc>

Dan semuanya di antaranya adalah kami membuat komponen web melakukan apa pun yang kami inginkan. Salah satu metode siklus hidup yang umum adalah connectedCallback, yang diaktifkan saat komponen web kita ditambahkan ke DOM. Kita bisa menggunakan metode itu untuk merender konten apa pun yang kita inginkan. Ingat, ini adalah kelas JS yang diwarisi dari HTMLElement, yang artinya kami this value adalah elemen komponen web itu sendiri, dengan semua metode manipulasi DOM normal yang sudah Anda ketahui dan sukai.

Paling sederhana, kita bisa melakukan ini:

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

... yang akan bekerja dengan baik.

Kata "hei" berwarna hijau.
Membangun Komponen Web Interoperable Yang Bahkan Bekerja Dengan React

Menambahkan konten nyata

Mari tambahkan beberapa konten interaktif yang bermanfaat. Kita butuh sebuah <span> untuk menahan nilai angka saat ini dan a <button> untuk menambah penghitung. Untuk saat ini, kami akan membuat konten ini di konstruktor kami dan menambahkannya ketika komponen web sebenarnya ada di 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();
}

Jika Anda benar-benar jijik dengan pembuatan DOM manual, ingatlah bahwa Anda dapat mengatur innerHTML, atau bahkan membuat elemen template sekali sebagai properti statis dari kelas komponen web Anda, mengkloningnya, dan menyisipkan konten untuk instans komponen web baru. Mungkin ada beberapa opsi lain yang tidak saya pikirkan, atau Anda selalu dapat menggunakan kerangka kerja komponen web seperti Lit or Setensilan. Namun untuk postingan kali ini, kami akan tetap membuatnya sederhana.

Selanjutnya, kita membutuhkan properti kelas JavaScript yang dapat diatur bernama value

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

Itu hanya properti kelas standar dengan setter, bersama dengan properti kedua untuk menyimpan nilainya. Satu twist yang menyenangkan adalah saya menggunakan sintaks properti kelas JavaScript pribadi untuk nilai-nilai ini. Itu berarti tidak seorang pun di luar komponen web kami dapat menyentuh nilai-nilai ini. Ini adalah JavaScript standar yang didukung di semua browser modern, jadi jangan takut untuk menggunakannya.

Atau jangan ragu untuk menyebutnya _value jika kamu memilih. Dan, terakhir, kami update Metode:

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

Berhasil!

Komponen web penghitung.
Membangun Komponen Web Interoperable Yang Bahkan Bekerja Dengan React

Jelas ini bukan kode yang ingin Anda pertahankan dalam skala besar. Berikut lengkapnya contoh kerja jika Anda ingin melihat lebih dekat. Seperti yang saya katakan, alat seperti Lit dan Stensil dirancang untuk membuat ini lebih sederhana.

Menambahkan beberapa fungsi lagi

Posting ini bukan menyelam jauh ke dalam komponen web. Kami tidak akan membahas semua API dan siklus hidup; kami bahkan tidak akan menutupi akar bayangan atau slot. Ada konten tak berujung pada topik tersebut. Tujuan saya di sini adalah untuk memberikan pengantar yang cukup layak untuk memicu minat, bersama dengan beberapa panduan yang berguna tentang sebenarnya menggunakan komponen web dengan kerangka kerja JavaScript populer yang sudah Anda kenal dan sukai.

Untuk itu, mari kita tingkatkan komponen web counter kita sedikit. Mari kita menerimanya color atribut, untuk mengontrol warna nilai yang ditampilkan. Dan mari kita juga menerimanya dan increment properti, sehingga konsumen komponen web ini dapat memilikinya meningkat 2, 3, 4 sekaligus. Dan untuk mendorong perubahan status ini, mari gunakan penghitung baru kita di kotak pasir Svelte โ€” kita akan segera ke React.

Kita akan mulai dengan komponen web yang sama seperti sebelumnya dan menambahkan atribut warna. Untuk mengonfigurasi komponen web kami untuk menerima dan merespons atribut, kami menambahkan static observedAttributes properti yang mengembalikan atribut yang didengarkan komponen web kita.

static observedAttributes = ["color"];

Dengan itu, kita dapat menambahkan attributeChangedCallback metode siklus hidup, yang akan berjalan setiap kali ada atribut yang terdaftar di observedAttributes diatur, atau diperbarui.

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

Sekarang kami memperbarui update metode untuk benar-benar menggunakannya:

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

Terakhir, mari tambahkan increment milik:

increment = 1;

Sederhana dan rendah hati.

Menggunakan komponen penghitung di Svelte

Mari kita gunakan apa yang baru saja kita buat. Kami akan masuk ke komponen aplikasi Svelte kami dan menambahkan sesuatu seperti ini:

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

Dan itu berhasil! Penghitung kami merender, menambah, dan dropdown memperbarui warna. Seperti yang Anda lihat, kami merender atribut warna di template Svelte kami dan, ketika nilainya berubah, Svelte menangani kerja keras pemanggilan setAttribute pada instance komponen web yang mendasari kami. Tidak ada yang istimewa di sini: ini adalah hal yang sama yang sudah dilakukan untuk atribut Apa pun elemen HTML.

Hal-hal menjadi sedikit menarik dengan increment menopang. Ini adalah tidak atribut pada komponen web kami; itu adalah prop di kelas komponen web. Itu berarti perlu disetel pada instance komponen web. Bersabarlah dengan saya, karena semuanya akan menjadi lebih sederhana dalam sedikit.

Pertama, kita akan menambahkan beberapa variabel ke komponen Svelte kita:

let increment = 1;
let wcInstance;

Pembangkit tenaga listrik kami dari komponen penghitung akan memungkinkan Anda menambah 1, atau 2:

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

Tapi, dalam teori, kita perlu mendapatkan instance sebenarnya dari komponen web kita. Ini adalah hal yang sama yang selalu kami lakukan setiap kali kami menambahkan ref dengan Bereaksi. Dengan Svelte, itu sederhana bind:this direktif:

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

Sekarang, di template Svelte kami, kami mendengarkan perubahan pada variabel kenaikan komponen kami dan mengatur properti komponen web yang mendasarinya.

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

Anda dapat mengujinya di demo langsung ini.

Kami jelas tidak ingin melakukan ini untuk setiap komponen web atau prop yang perlu kami kelola. Bukankah lebih baik jika kita bisa mengatur increment tepat di komponen web kami, di markup, seperti yang biasa kami lakukan untuk properti komponen, dan memilikinya, Anda tahu, bekerja saja? Dengan kata lain, alangkah baiknya jika kita bisa menghapus semua penggunaan wcInstance dan gunakan kode yang lebih sederhana ini sebagai gantinya:

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

Ternyata kita bisa. Kode ini berfungsi; Svelte menangani semua kerja keras itu untuk kami. Lihat di demo ini. Ini adalah perilaku standar untuk hampir semua kerangka kerja JavaScript.

Jadi mengapa saya menunjukkan cara manual untuk menyetel prop komponen web? Dua alasan: ini berguna untuk memahami bagaimana hal ini bekerja dan, beberapa saat yang lalu, saya katakan ini bekerja untuk "hampir" semua kerangka kerja JavaScript. Tapi ada satu kerangka kerja yang, sayangnya, tidak mendukung pengaturan prop komponen web seperti yang baru saja kita lihat.

Bereaksi adalah binatang yang berbeda

Membangun Komponen Web yang Dapat Dioperasikan Yang Bahkan Bekerja Dengan React PlatoBlockchain Data Intelligence. Pencarian Vertikal. ai.
Membangun Komponen Web Interoperable Yang Bahkan Bekerja Dengan React

Reaksi. Kerangka kerja JavaScript paling populer di planet ini tidak mendukung interop dasar dengan komponen web. Ini adalah masalah terkenal yang unik untuk React. Menariknya, ini sebenarnya diperbaiki di cabang eksperimental React, tetapi untuk beberapa alasan tidak digabungkan ke versi 18. Yang mengatakan, kita masih bisa lacak kemajuannya. Dan Anda dapat mencobanya sendiri dengan live demo.

Solusinya, tentu saja, adalah dengan menggunakan ref, ambil instance komponen web, dan atur secara manual increment ketika nilai itu berubah. Ini terlihat seperti ini:

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

Seperti yang telah kita diskusikan, pengkodean ini secara manual untuk setiap properti komponen web sama sekali tidak dapat diskalakan. Tapi semua tidak hilang karena kami memiliki beberapa pilihan.

Opsi 1: Gunakan atribut di mana saja

Kami memiliki atribut. Jika Anda mengklik demo React di atas, tombol increment prop tidak berfungsi, tetapi warnanya berubah dengan benar. Tidak bisakah kita mengkodekan semuanya dengan atribut? Sayangnya tidak. Nilai atribut hanya dapat berupa string. Itu cukup bagus di sini, dan kita akan bisa melangkah lebih jauh dengan pendekatan ini. Angka seperti increment dapat dikonversi ke dan dari string. Kami bahkan dapat JSON merangkai/mengurai objek. Namun pada akhirnya kita harus meneruskan sebuah fungsi ke dalam komponen web, dan pada saat itu kita akan kehabisan pilihan.

Opsi 2: Bungkus itu

Ada pepatah lama bahwa Anda dapat memecahkan masalah apa pun dalam ilmu komputer dengan menambahkan tingkat tipuan (kecuali masalah terlalu banyak tingkat tipuan). Kode untuk mengatur alat peraga ini cukup dapat diprediksi dan sederhana. Bagaimana jika kita menyembunyikannya di perpustakaan? Orang-orang pintar di belakang Lit punya satu solusi. Pustaka ini membuat komponen React baru untuk Anda setelah Anda memberinya komponen web, dan mencantumkan properti yang dibutuhkannya. Meskipun pintar, saya bukan penggemar pendekatan ini.

Daripada memiliki pemetaan komponen web satu-ke-satu ke komponen React yang dibuat secara manual, yang saya sukai hanyalah satu Bereaksi komponen yang kami lewati komponen web kami nama tag kepada (counter-wc dalam kasus kami) โ€” bersama dengan semua atribut dan properti โ€” dan agar komponen ini merender komponen web kami, tambahkan ref, lalu cari tahu apa itu prop dan apa itu atribut. Itu solusi ideal menurut saya. Saya tidak tahu perpustakaan yang melakukan ini, tetapi harus mudah dibuat. Mari kita mencobanya!

Ini adalah pemakaian kami sedang mencari:

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

wcTag adalah nama tag komponen web; sisanya adalah properti dan atribut yang ingin kita sampaikan.

Inilah yang terlihat seperti implementasi saya:

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

Baris yang paling menarik ada di akhir:

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

Inilah cara kami membuat elemen di React dengan nama dinamis. Faktanya, inilah yang React biasanya transpile ke JSX. Semua div kami dikonversi ke createElement("div") panggilan. Kami biasanya tidak perlu memanggil API ini secara langsung, tetapi API ini ada saat kami membutuhkannya.

Di luar itu, kami ingin menjalankan efek tata letak dan mengulang setiap prop yang telah kami berikan ke komponen kami. Kami mengulang semuanya dan memeriksa untuk melihat apakah itu properti dengan in check yang memeriksa objek instance komponen web serta rantai prototipenya, yang akan menangkap getter/setter apa pun yang muncul di prototipe kelas. Jika tidak ada properti seperti itu, itu dianggap sebagai atribut. Dalam kedua kasus, kami hanya mengaturnya jika nilainya benar-benar berubah.

Jika Anda bertanya-tanya mengapa kami menggunakan useLayoutEffect alih-alih useEffect, itu karena kami ingin segera menjalankan pembaruan ini sebelum konten kami dirender. Juga, perhatikan bahwa kami tidak memiliki larik dependensi ke . kami useLayoutEffect; ini berarti kami ingin menjalankan pembaruan ini pada setiap render. Ini bisa berisiko karena React cenderung merender ulang banyak. Saya memperbaiki ini dengan membungkus semuanya React.memo. Ini pada dasarnya adalah versi modern dari React.PureComponent, yang berarti komponen hanya akan dirender ulang jika salah satu properti sebenarnya telah berubah โ€” dan komponen tersebut memeriksa apakah itu terjadi melalui pemeriksaan kesetaraan sederhana.

Satu-satunya risiko di sini adalah jika Anda melewati prop objek yang Anda mutasi secara langsung tanpa menetapkan ulang, maka Anda tidak akan melihat pembaruan. Tapi ini sangat tidak disarankan, terutama di komunitas React, jadi saya tidak akan mengkhawatirkannya.

Sebelum melanjutkan, saya ingin menyebutkan satu hal terakhir. Anda mungkin tidak senang dengan tampilan penggunaannya. Sekali lagi, komponen ini digunakan seperti ini:

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

Secara khusus, Anda mungkin tidak suka meneruskan nama tag komponen web ke <WcWrapper> komponen dan lebih suka @lit-labs/react paket di atas, yang membuat komponen React individu baru untuk setiap komponen web. Itu benar-benar adil dan saya mendorong Anda untuk menggunakan apa pun yang paling nyaman bagi Anda. Tapi bagi saya, satu keuntungan dengan pendekatan ini adalah mudah untuk hapus. Jika dengan keajaiban, React menggabungkan penanganan komponen web yang tepat dari cabang eksperimental mereka menjadi main besok, Anda dapat mengubah kode di atas dari ini:

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

โ€ฆuntuk ini:

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

Anda bahkan mungkin bisa menulis satu codemod untuk melakukannya di mana-mana, dan kemudian menghapus <WcWrapper> sama sekali. Sebenarnya, coret itu: pencarian global dan ganti dengan RegEx mungkin akan berhasil.

Pelaksanaan

Aku tahu, sepertinya butuh perjalanan untuk sampai ke sini. Jika Anda ingat, tujuan awal kami adalah untuk mengambil kode pratinjau gambar yang kami lihat di my memuat posting, dan pindahkan ke komponen web sehingga dapat digunakan dalam kerangka kerja JavaScript apa pun. Kurangnya interop yang tepat di React menambahkan banyak detail ke dalam campuran. Tapi sekarang kita memiliki pegangan yang layak tentang cara membuat komponen web, dan menggunakannya, implementasinya akan hampir anti-klimaks.

Saya akan meletakkan seluruh komponen web di sini dan menyebutkan beberapa bagian yang menarik. Jika Anda ingin melihatnya beraksi, ini dia demo kerja. Ini akan beralih di antara tiga buku favorit saya di tiga bahasa pemrograman favorit saya. URL untuk setiap buku akan unik setiap kali, sehingga Anda dapat melihat pratinjau, meskipun Anda mungkin ingin membatasi hal-hal di tab Jaringan DevTools Anda untuk benar-benar melihat hal-hal yang terjadi.

Lihat seluruh kode
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); }
}

Pertama, kami mendaftarkan atribut yang kami minati dan bereaksi ketika berubah:

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

Ini menyebabkan komponen gambar kami dibuat, yang hanya akan ditampilkan saat dimuat:

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

Selanjutnya kami memiliki properti pratinjau kami, yang dapat berupa string pratinjau base64 kami, atau kami blurhash paket:

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

Ini mengacu pada fungsi pembantu mana pun yang kita butuhkan:

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

Dan, terakhir, kami render Metode:

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

Dan beberapa metode pembantu untuk menyatukan semuanya:

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

Ini sedikit lebih banyak daripada yang kita perlukan jika kita membangun ini dalam sebuah kerangka kerja, tetapi keuntungannya adalah bahwa kita dapat menggunakan kembali ini dalam kerangka apa pun yang kita inginkan โ€” meskipun React akan membutuhkan pembungkus untuk saat ini, seperti yang telah kita diskusikan .

Barang sisa

Saya telah menyebutkan pembungkus Lit's React. Tetapi jika Anda menemukan diri Anda menggunakan Stensil, itu sebenarnya mendukung a pipa keluaran terpisah hanya untuk Bereaksi. Dan orang-orang baik di Microsoft juga membuat sesuatu yang mirip dengan pembungkus Lit, dilampirkan ke pustaka komponen web Cepat.

Seperti yang saya sebutkan, semua kerangka kerja yang tidak bernama React akan menangani pengaturan properti komponen web untuk Anda. Perhatikan bahwa beberapa memiliki beberapa rasa sintaksis khusus. Misalnya, dengan Solid.js, <your-wc value={12}> selalu berasumsi bahwa value adalah properti, yang dapat Anda timpa dengan attr awalan, seperti <your-wc attr:value={12}>.

Membungkus

Komponen web adalah bagian yang menarik dan sering kurang dimanfaatkan dari lanskap pengembangan web. Mereka dapat membantu mengurangi ketergantungan Anda pada kerangka kerja JavaScript tunggal dengan mengelola UI Anda, atau komponen "daun". Saat membuat ini sebagai komponen web โ€” sebagai lawan dari komponen Svelte atau React โ€” tidak akan ergonomis, keuntungannya adalah mereka akan dapat digunakan kembali secara luas.


Membangun Komponen Web Interoperable Yang Bahkan Bekerja Dengan React awalnya diterbitkan pada Trik CSS. Kamu harus dapatkan buletin.

Stempel Waktu:

Lebih dari Trik CSS