ساخت اجزای وب قابل همکاری که حتی با هوش داده‌های React PlatoBlockchain کار می‌کنند. جستجوی عمودی Ai.

ساخت اجزای وب قابل همکاری که حتی با React کار می کنند

کسانی از ما که بیش از چند سال توسعه‌دهنده وب بوده‌اند، احتمالاً با استفاده از بیش از یک چارچوب جاوا اسکریپت کد نوشته‌اند. با همه انتخاب‌های موجود - React، Svelte، Vue، Angular، Solid - همه چیز اجتناب‌ناپذیر است. یکی از ناامیدکننده‌ترین چیزهایی که هنگام کار در فریم‌ورک‌ها باید با آن دست و پنجه نرم کنیم، ایجاد مجدد همه آن اجزای رابط کاربری سطح پایین است: دکمه‌ها، برگه‌ها، فهرست‌های بازشو و غیره. آنچه به‌ویژه ناامیدکننده است این است که معمولاً آنها را در یک چارچوب تعریف می‌کنیم. مثلاً React، اما اگر می‌خواهیم چیزی در Svelte بسازیم، باید آن‌ها را بازنویسی کنیم. یا Vue. یا جامد. و غیره.

آیا بهتر نیست که بتوانیم این مؤلفه های رابط کاربری سطح پایین را یک بار به روشی فریمورک-آگنوستیک تعریف کنیم و سپس بین فریم ورک ها دوباره از آنها استفاده کنیم؟ البته که می شود! و ما می توانیم؛ اجزای وب راه هستند. این پست به شما نشان می دهد که چگونه.

در حال حاضر، داستان SSR برای اجزای وب کمی کم است. DOM سایه اظهاری (DSD) نحوه رندر شدن یک مؤلفه وب در سمت سرور است، اما از زمان نگارش این مقاله، با چارچوب های برنامه مورد علاقه شما مانند Next، Remix یا SvelteKit یکپارچه نشده است. اگر این یک نیاز برای شماست، حتما آخرین وضعیت DSD را بررسی کنید. اما در غیر این صورت، اگر SSR چیزی نیست که از آن استفاده می کنید، ادامه مطلب را بخوانید.

اول، برخی زمینه ها

اجزای وب اساساً عناصر HTML هستند که خودتان آنها را تعریف می کنید <yummy-pizza> یا هر چیز دیگری، از پایه. آنها در اینجا در CSS-Tricks (از جمله مجموعه ای گسترده از کالب ویلیامز و یکی از جان رئا) اما ما به طور خلاصه روند را مرور خواهیم کرد. در اصل، شما یک کلاس جاوا اسکریپت را تعریف می کنید و آن را از آن به ارث می برید HTMLElementو سپس هر ویژگی، ویژگی و سبکی را که کامپوننت وب دارد و البته نشانه گذاری که در نهایت به کاربران شما ارائه می دهد را تعریف کنید.

توانایی تعریف عناصر HTML سفارشی که به هیچ جزء خاص محدود نمی شوند، هیجان انگیز است. اما این آزادی نیز یک محدودیت است. وجود مستقل از هر چارچوب جاوا اسکریپت به این معنی است که واقعاً نمی توانید با آن چارچوب های جاوا اسکریپت تعامل داشته باشید. یک مؤلفه React را در نظر بگیرید که برخی از داده ها را واکشی می کند و سپس برخی را ارائه می دهد دیگر کامپوننت واکنش، انتقال داده ها در امتداد. این واقعاً به عنوان یک مؤلفه وب کار نمی کند، زیرا یک مؤلفه وب نمی داند چگونه یک مؤلفه React را ارائه دهد.

اجزای وب به ویژه به عنوان اکسل اجزای برگ. اجزای برگ آخرین چیزی هستند که در درخت جزء ارائه می شوند. اینها مؤلفه هایی هستند که برخی از لوازم را دریافت می کنند و برخی را ارائه می دهند UI. اینها هستند نه مؤلفه‌هایی که در وسط درخت مؤلفه شما نشسته‌اند، داده‌ها را ارسال می‌کنند، زمینه را تنظیم می‌کنند، و غیره - فقط قطعات خالص UI بدون توجه به اینکه کدام چارچوب جاوا اسکریپت بقیه برنامه را تامین می کند، یکسان به نظر می رسد.

کامپوننت وب که در حال ساختن آن هستیم

به جای ساختن چیزی خسته کننده (و معمول)، مانند یک دکمه، بیایید چیزی کمی متفاوت بسازیم. در من بارگذاری پست ما به استفاده از پیش‌نمایش‌های تار تصویر برای جلوگیری از جریان مجدد محتوا و ارائه یک رابط کاربری مناسب برای کاربران در حین بارگیری تصاویرمان نگاه کردیم. ما به base64 نگاه کردیم که نسخه‌های تار و تخریب‌شده‌ای از تصاویر ما را رمزگذاری می‌کند و در حالی که تصویر واقعی بارگذاری می‌شود، آن را در رابط کاربری ما نشان می‌دهد. ما همچنین به تولید پیش‌نمایش‌های بسیار فشرده و تار با استفاده از ابزاری به نام نگاه کردیم بلورهش.

آن پست به شما نشان داد که چگونه آن پیش نمایش ها را تولید کنید و از آنها در پروژه React استفاده کنید. این پست به شما نشان می دهد که چگونه از آن پیش نمایش ها از یک مؤلفه وب استفاده کنید تا بتوان از آنها استفاده کرد هر چارچوب جاوا اسکریپت

اما قبل از اینکه بتوانیم بدویم باید راه برویم، بنابراین ابتدا چیزهای بی اهمیت و احمقانه ای را مرور می کنیم تا ببینیم اجزای وب دقیقا چگونه کار می کنند.

همه چیز در این پست بدون هیچ ابزاری اجزای وب وانیلی را می سازد. این بدان معناست که کد کمی دیگ بخار خواهد داشت، اما باید نسبتاً آسان باشد. ابزارهایی مانند لیت or شابلون برای ساخت اجزای وب طراحی شده اند و می توان از آنها برای حذف بیشتر این صفحه دیگ استفاده کرد. من از شما می خواهم که آنها را بررسی کنید! اما برای این پست، در ازای عدم نیاز به معرفی و آموزش وابستگی دیگر، کمی دیگ بخار بیشتر را ترجیح می دهم.

یک جزء شمارنده ساده

بیایید «Hello World» کلاسیک اجزای جاوا اسکریپت را بسازیم: یک شمارنده. ما یک مقدار و یک دکمه که آن مقدار را افزایش می دهد، ارائه می دهیم. ساده و خسته کننده است، اما به ما اجازه می دهد ساده ترین مؤلفه وب ممکن را بررسی کنیم.

برای ساختن یک کامپوننت وب، اولین قدم ساختن کلاس جاوا اسکریپت است که از HTMLElement:

class Counter extends HTMLElement {}

آخرین مرحله ثبت کامپوننت وب است، اما فقط در صورتی که قبلاً آن را ثبت نکرده باشیم:

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

و البته آن را رندر کنید:

<counter-wc></counter-wc>

و همه چیز در این بین باعث می شود که مؤلفه وب هر کاری را که می خواهیم انجام دهد. یکی از روش های متداول چرخه عمر این است connectedCallback، که وقتی کامپوننت وب ما به DOM اضافه می شود فعال می شود. ما می‌توانیم از این روش برای ارائه هر محتوایی که می‌خواهیم استفاده کنیم. به یاد داشته باشید، این یک کلاس JS است که از آن به ارث برده شده است HTMLElement، که به معنی ماست this ارزش خود عنصر مؤلفه وب است، با تمام روش‌های دستکاری DOM معمولی که قبلاً می‌شناسید و دوست دارید.

در ساده ترین حالت، می توانیم این کار را انجام دهیم:

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

... که به خوبی کار خواهد کرد.

کلمه "هی" به رنگ سبز.
ساخت اجزای وب قابل همکاری که حتی با React کار می کنند

اضافه کردن محتوای واقعی

بیایید چند محتوای مفید و تعاملی اضافه کنیم. ما نیاز داریم a <span> برای نگه داشتن مقدار عدد فعلی و a <button> برای افزایش شمارنده در حال حاضر، ما این محتوا را در سازنده خود ایجاد می کنیم و زمانی که مؤلفه وب واقعاً در 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();
}

اگر واقعاً از ایجاد DOM دستی ناراحت شدید، به یاد داشته باشید که می‌توانید تنظیم کنید innerHTML، یا حتی یک بار یک عنصر الگو را به عنوان ویژگی ثابت کلاس کامپوننت وب خود ایجاد کنید، آن را شبیه سازی کنید و محتویات را برای نمونه های کامپوننت وب جدید درج کنید. احتمالاً گزینه های دیگری وجود دارد که من به آنها فکر نمی کنم، یا همیشه می توانید از یک چارچوب کامپوننت وب مانند استفاده کنید لیت or شابلون. اما برای این پست، ما به ساده نگه داشتن آن ادامه می دهیم.

در ادامه به یک ویژگی کلاس جاوا اسکریپت قابل تنظیم به نام نیاز داریم value

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

این فقط یک ویژگی کلاس استاندارد با یک تنظیم کننده، همراه با یک ویژگی دوم برای نگه داشتن مقدار است. یک پیچ جالب این است که من از نحو خصوصی کلاس جاوا اسکریپت برای این مقادیر استفاده می کنم. این بدان معناست که هیچ کس خارج از مؤلفه وب ما هرگز نمی تواند این مقادیر را لمس کند. این جاوا اسکریپت استاندارد است که در تمام مرورگرهای مدرن پشتیبانی می شود، پس از استفاده از آن نترسید.

یا با خیال راحت با آن تماس بگیرید _value اگر ترجیح می دهید و در آخر، ما update روش:

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

کار می کند!

جزء وب شمارنده.
ساخت اجزای وب قابل همکاری که حتی با React کار می کنند

بدیهی است که این کدی نیست که شما بخواهید در مقیاس آن را حفظ کنید. اینجا کامل است نمونه کار اگر می خواهید از نزدیک نگاه کنید همانطور که گفتم، ابزارهایی مانند Lit و Stencil برای ساده‌تر کردن این کار طراحی شده‌اند.

افزودن برخی قابلیت های بیشتر

این پست یک فرو رفتن عمیق در اجزای وب نیست. ما همه APIها و چرخه های عمر را پوشش نمی دهیم. ما حتی پوشش نمی دهیم ریشه های سایه یا شکاف ها. مطالب بی پایانی در مورد آن موضوعات وجود دارد. هدف من در اینجا ارائه یک مقدمه مناسب به اندازه کافی برای ایجاد علاقه، همراه با برخی راهنمایی های مفید در مورد واقعی است. با استفاده از اجزای وب با چارچوب های محبوب جاوا اسکریپت که قبلاً می شناسید و دوست دارید.

برای این منظور، اجازه دهید کامپوننت وب پیشخوان خود را کمی تقویت کنیم. اجازه دهید آن را بپذیرد color ویژگی، برای کنترل رنگ مقداری که نمایش داده می شود. و همچنین اجازه دهید آن را بپذیرد increment ویژگی، بنابراین مصرف کنندگان این کامپوننت وب می توانند آن را هر بار 2، 3، 4 افزایش دهند. و برای ایجاد این تغییرات حالت، بیایید از شمارنده جدید خود در جعبه شنی Svelte استفاده کنیم - کمی بعد به React خواهیم رسید.

ما با همان مؤلفه وب مانند قبل شروع می کنیم و یک ویژگی رنگ اضافه می کنیم. برای پیکربندی کامپوننت وب ما برای پذیرش و پاسخ به یک ویژگی، یک استاتیک اضافه می کنیم observedAttributes ویژگی هایی که ویژگی هایی را که کامپوننت وب ما به آنها گوش می دهد برمی گرداند.

static observedAttributes = ["color"];

با وجود آن، می توانیم a اضافه کنیم attributeChangedCallback روش چرخه عمر، که هر زمان که هر یک از ویژگی های ذکر شده در آن اجرا می شود observedAttributes تنظیم شده یا به روز می شوند.

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

اکنون ما خود را به روز می کنیم update روش استفاده واقعی از آن:

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

در آخر، بیایید ما را اضافه کنیم increment ویژگی:

increment = 1;

ساده و متواضع.

استفاده از مولفه شمارنده در Svelte

بیایید از چیزی که تازه ساختیم استفاده کنیم. ما وارد جزء برنامه Svelte خود می شویم و چیزی شبیه به این اضافه می کنیم:

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

و کار می کند! شمارنده ما رندر می‌شود، افزایش می‌یابد، و منوی کشویی رنگ را به‌روزرسانی می‌کند. همانطور که می بینید، ما ویژگی رنگ را در قالب Svelte خود رندر می کنیم و هنگامی که مقدار تغییر می کند، Svelte وظیفه فراخوانی را انجام می دهد. setAttribute در نمونه اصلی مؤلفه وب ما. هیچ چیز خاصی در اینجا وجود ندارد: این همان کاری است که قبلاً برای ویژگی های انجام می دهد هر عنصر HTML.

چیزها کمی جالب می شوند increment پشتیبانی این هست نه یک ویژگی در مؤلفه وب ما؛ این یک تکیه گاه در کلاس جزء وب است. یعنی باید روی نمونه کامپوننت وب تنظیم شود. من را تحمل کنید، زیرا همه چیز در مدت کوتاهی بسیار ساده تر خواهد شد.

ابتدا چند متغیر به مولفه Svelte خود اضافه می کنیم:

let increment = 1;
let wcInstance;

نیروگاه یک جزء شمارنده ما به شما اجازه می دهد 1 یا 2 افزایش دهید:

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

اما، در تئوری، باید نمونه واقعی کامپوننت وب خود را بدست آوریم. این همان کاری است که ما همیشه هر زمان که a اضافه می کنیم انجام می دهیم ref با React. با Svelte، این یک کار ساده است bind:this دستورالعمل:

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

اکنون، در قالب Svelte، به تغییرات متغیر افزایشی مؤلفه خود گوش می دهیم و خاصیت مؤلفه وب زیرین را تنظیم می کنیم.

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

می توانید آن را تست کنید در این دمو زنده.

بدیهی است که ما نمی‌خواهیم این کار را برای هر مؤلفه وبی که باید مدیریت کنیم، انجام دهیم. آیا خوب نیست اگر بتوانیم تنظیم کنیم increment درست بر روی کامپوننت وب ما، در نشانه گذاری، همانطور که ما معمولاً برای قطعات کامپوننت انجام می دهیم، و می دانید، فقط کار? به عبارت دیگر، اگر بتوانیم همه موارد استفاده از آن را حذف کنیم، خوب است wcInstance و به جای آن از این کد ساده تر استفاده کنید:

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

معلوم می شود ما می توانیم. این کد کار می کند. Svelte تمام این کارها را برای ما انجام می دهد. آن را در این دمو بررسی کنید. این رفتار استاندارد تقریباً برای همه فریمورک های جاوا اسکریپت است.

پس چرا راه دستی تنظیم پایه کامپوننت وب را به شما نشان دادم؟ دو دلیل: مفید است که بدانید این چیزها چگونه کار می کنند و چند لحظه پیش گفتم که این کار برای تمام فریمورک های جاوا اسکریپت «تقریباً» کار می کند. اما یک فریمورک وجود دارد که به طرز دیوانه‌کننده‌ای از تنظیمات پایه کامپوننت وب مانند آنچه که قبلاً دیدیم پشتیبانی نمی‌کند.

React یک جانور متفاوت است

ساخت اجزای وب قابل همکاری که حتی با هوش داده‌های React PlatoBlockchain کار می‌کنند. جستجوی عمودی Ai.
ساخت اجزای وب قابل همکاری که حتی با React کار می کنند

واکنش نشان دهید. محبوب ترین چارچوب جاوا اسکریپت در این سیاره از تعامل اولیه با اجزای وب پشتیبانی نمی کند. این یک مشکل شناخته شده است که مختص React است. جالب اینجاست که این در واقع در شاخه آزمایشی React ثابت شده است، اما به دلایلی در نسخه 18 ادغام نشده است. پیشرفت آن را پیگیری کنید. و شما می توانید این را خودتان با یک امتحان کنید نسخه ی نمایشی زنده.

البته راه حل استفاده از الف است ref، نمونه کامپوننت وب را بگیرید و به صورت دستی تنظیم کنید increment زمانی که آن مقدار تغییر می کند. به نظر می رسد این است:

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

همانطور که بحث کردیم، کدنویسی به صورت دستی برای هر ویژگی کامپوننت وب به سادگی مقیاس پذیر نیست. اما همه چیز از دست نمی رود زیرا ما چند گزینه داریم.

گزینه 1: از ویژگی ها در همه جا استفاده کنید

ما صفاتی داریم. اگر روی دموی React در بالا کلیک کردید، increment پایه کار نمی کرد، اما رنگ به درستی تغییر کرد. آیا نمی توانیم همه چیز را با ویژگی ها کدگذاری کنیم؟ متاسفانه نه. مقادیر مشخصه فقط می توانند رشته باشند. در اینجا به اندازه کافی خوب است، و ما می توانیم با این رویکرد تا حدودی جلو برویم. اعداد مانند increment را می توان به رشته ها و از رشته ها تبدیل کرد. ما حتی می‌توانیم با JSON اشیاء را رشته‌بندی/تجزیه کنیم. اما در نهایت باید یک تابع را به یک کامپوننت وب منتقل کنیم، و در آن مرحله از گزینه‌ها خارج می‌شویم.

گزینه 2: آن را بپیچید

یک ضرب المثل قدیمی وجود دارد که می گوید شما می توانید هر مشکلی را در علوم کامپیوتر با اضافه کردن یک سطح غیرمستقیم حل کنید (به جز مشکل سطوح بیش از حد غیرمستقیم). کد تنظیم این لوازم بسیار قابل پیش بینی و ساده است. اگر آن را در کتابخانه مخفی کنیم چه؟ افراد باهوش پشت لیت یک راه حل داشته باشید. این کتابخانه پس از اینکه یک کامپوننت وب به آن دادید یک کامپوننت React جدید برای شما ایجاد می کند و ویژگی های مورد نیازش را فهرست می کند. در حالی که باهوش هستم، من طرفدار این رویکرد نیستم.

به جای نگاشت یک به یک اجزای وب به اجزای React که به صورت دستی ایجاد شده اند، چیزی که ترجیح می دهم این است که یک کامپوننت واکنشی که ما جزء وب خود را پاس می کنیم نام تگ به (counter-wc در مورد ما) - به همراه تمام ویژگی ها و ویژگی ها - و برای اینکه این کامپوننت کامپوننت وب ما را ارائه کند، آن را اضافه کنید ref، سپس بفهمید که یک prop چیست و چه ویژگی است. این راه حل ایده آل به نظر من است. من کتابخانه ای را نمی شناسم که این کار را انجام دهد، اما ایجاد آن باید ساده باشد. بیایید به آن ضربه بزنیم!

این است استفاده ما به دنبال:

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

wcTag نام تگ جزء وب است. بقیه ویژگی ها و ویژگی هایی هستند که ما می خواهیم به آنها منتقل شود.

در اینجا پیاده سازی من به نظر می رسد:

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

جالب ترین خط در پایان است:

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

به این ترتیب یک عنصر در React با نام پویا ایجاد می کنیم. در واقع، این همان چیزی است که React به طور معمول JSX را به آن تبدیل می کند. همه div های ما تبدیل به createElement("div") تماس می گیرد. ما معمولاً نیازی به تماس مستقیم با این API نداریم، اما زمانی که به آن نیاز داشته باشیم وجود دارد.

فراتر از آن، ما می‌خواهیم یک افکت طرح‌بندی را اجرا کنیم و از طریق هر پایه‌ای که به کامپوننت خود منتقل کرده‌ایم حلقه بزنیم. ما از طریق همه آنها حلقه می زنیم و بررسی می کنیم که آیا این ویژگی دارای یک است یا خیر in بررسی کنید که شی نمونه کامپوننت وب و همچنین زنجیره نمونه اولیه آن را بررسی می کند، که هر گیرنده/تنظیم کننده ای را که در نمونه اولیه کلاس قرار می گیرد را می گیرد. اگر چنین خاصیتی وجود نداشته باشد، به عنوان یک ویژگی فرض می شود. در هر صورت، فقط در صورتی آن را تنظیم می کنیم که مقدار آن واقعاً تغییر کرده باشد.

اگر تعجب می کنید که چرا ما استفاده می کنیم useLayoutEffect بجای useEffect، به این دلیل است که می خواهیم بلافاصله این به روز رسانی ها را قبل از رندر شدن محتوای خود اجرا کنیم. همچنین، توجه داشته باشید که ما هیچ آرایه وابستگی به خود نداریم useLayoutEffect; این بدان معنی است که ما می خواهیم این به روز رسانی را اجرا کنیم هر رندر. این می تواند خطرناک باشد زیرا React تمایل به رندر مجدد دارد زیاد. من این را با پیچیدن کل چیز در آن بهبود می بخشم React.memo. این در اصل نسخه مدرن است React.PureComponent، به این معنی که کامپوننت فقط در صورتی دوباره رندر می شود که هر یک از اجزای اصلی آن تغییر کرده باشد - و بررسی می کند که آیا این اتفاق از طریق یک بررسی برابری ساده رخ داده است یا خیر.

تنها خطری که در اینجا وجود دارد این است که اگر یک شیء را که مستقیماً بدون تخصیص مجدد جهش می دهید، ارسال کنید، به روز رسانی ها را نخواهید دید. اما این بسیار ناامید است، به خصوص در جامعه React، بنابراین من نگران آن نیستم.

قبل از ادامه، می‌خواهم آخرین نکته را بگویم. ممکن است از نحوه استفاده راضی نباشید. باز هم از این کامپوننت به صورت زیر استفاده می شود:

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

به طور خاص، ممکن است دوست نداشته باشید که نام تگ مؤلفه وب را به آن منتقل کنید <WcWrapper> جزء و ترجیح می دهند به جای @lit-labs/react بسته فوق، که یک مؤلفه React جدید برای هر مؤلفه وب ایجاد می کند. این کاملاً منصفانه است و من شما را تشویق می کنم که از هر چیزی که راحت تر هستید استفاده کنید. اما برای من، یکی از مزیت های این رویکرد این است که انجام آن آسان است حذف کردن. اگر به‌عنوان معجزه‌ای، React مدیریت صحیح مؤلفه‌های وب را از شاخه آزمایشی خود در آن ادغام کند main فردا می توانید کد بالا را از این زیر تغییر دهید:

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

…به این:

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

شما احتمالاً حتی می توانید یک کد مود واحد بنویسید تا این کار را در همه جا انجام دهید و سپس حذف کنید <WcWrapper> در مجموع در واقع، آن را خراش دهید: جستجوی جهانی و جایگزینی با RegEx احتمالاً کارساز خواهد بود.

اجرا

می دانم، به نظر می رسد که برای رسیدن به اینجا یک سفر طول کشیده است. اگر به خاطر داشته باشید، هدف اصلی ما این بود که کد پیش‌نمایش تصویر را که در من نگاه می‌کردیم، بگیریم بارگذاری پستو آن را به یک مؤلفه وب منتقل کنید تا بتوان از آن در هر چارچوب جاوا اسکریپت استفاده کرد. عدم وجود تعامل مناسب React جزئیات زیادی را به ترکیب اضافه کرد. اما اکنون که مدیریت مناسبی در مورد نحوه ایجاد یک مؤلفه وب و استفاده از آن داریم، پیاده سازی تقریباً ضد اقلیم خواهد بود.

من کل مؤلفه وب را در اینجا رها می کنم و برخی از بیت های جالب را بیان می کنم. اگر می خواهید آن را در عمل ببینید، در اینجا یک نسخه ی نمایشی کار. بین سه کتاب مورد علاقه من در سه زبان برنامه نویسی مورد علاقه من جابه جا می شود. URL برای هر کتاب هر بار منحصر به فرد خواهد بود، بنابراین می توانید پیش نمایش را ببینید، اگرچه احتمالاً می خواهید چیزهایی را در برگه DevTools Network خود کنترل کنید تا واقعاً چیزهایی را که در حال وقوع هستند ببینید.

مشاهده کل کد
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); }
}

ابتدا ویژگی مورد علاقه خود را ثبت می کنیم و زمانی که تغییر می کند واکنش نشان می دهیم:

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

این باعث می شود کامپوننت تصویر ما ایجاد شود که فقط هنگام بارگذاری نشان داده می شود:

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

در مرحله بعد، ویژگی پیش‌نمایش خود را داریم، که می‌تواند رشته پیش‌نمایش base64 یا ما باشد blurhash بسته:

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

این به هر تابع کمکی که نیاز داریم موکول می شود:

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

و در آخر، ما render روش:

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

و چند روش کمکی برای گره زدن همه چیز به هم:

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

اگر این را در یک فریمورک بسازیم کمی بیشتر از چیزی است که نیاز داریم، اما نکته مثبت این است که می‌توانیم در هر چارچوبی که می‌خواهیم دوباره از آن استفاده کنیم - اگرچه React در حال حاضر به یک wrapper نیاز دارد، همانطور که بحث کردیم. .

خرت و پرت

من قبلاً به لفاف Lit's React اشاره کردم. اما اگر متوجه شدید که از Stencil استفاده می کنید، در واقع از a پشتیبانی می کند خط خروجی جداگانه فقط برای React. و افراد خوب مایکروسافت نیز چنین کرده اند چیزی شبیه به لفاف Lit ایجاد کرد، به کتابخانه کامپوننت وب سریع پیوست شده است.

همانطور که اشاره کردم، همه فریم ورک هایی که React نام ندارند، تنظیمات ویژگی های کامپوننت وب را برای شما انجام می دهند. فقط توجه داشته باشید که برخی از آنها طعم خاصی از نحو دارند. به عنوان مثال، با Solid.js، <your-wc value={12}> همیشه این را فرض می کند value یک ویژگی است که می توانید با یک آن را لغو کنید attr پیشوند، مانند <your-wc attr:value={12}>.

پسگفتار

اجزای وب یک بخش جالب و اغلب کم استفاده از چشم انداز توسعه وب هستند. آنها می توانند با مدیریت UI یا اجزای "برگ" شما به کاهش وابستگی شما به هر چارچوب جاوا اسکریپت کمک کنند. در حالی که ایجاد این کامپوننت‌ها به‌عنوان کامپوننت‌های وب – بر خلاف کامپوننت‌های Svelte یا React – چندان ارگونومیک نخواهد بود، اما نکته مثبت این است که به‌طور گسترده قابل استفاده مجدد خواهند بود.


ساخت اجزای وب قابل همکاری که حتی با React کار می کنند در ابتدا منتشر شد ترفندهای CSS. تو باید دریافت خبرنامه.

تمبر زمان:

بیشتر از ترفندهای CSS