इंटरऑपरेबल वेब घटकों का निर्माण जो रिएक्ट प्लेटोब्लॉकचेन डेटा इंटेलिजेंस के साथ भी काम करते हैं। लंबवत खोज. ऐ.

इंटरऑपरेबल वेब घटकों का निर्माण जो प्रतिक्रिया के साथ भी काम करते हैं

हममें से जो कुछ वर्षों से अधिक समय से वेब डेवलपर रहे हैं, उन्होंने शायद एक से अधिक जावास्क्रिप्ट ढांचे का उपयोग करके कोड लिखा है। सभी विकल्पों के साथ - रिएक्ट, स्वेल्टे, वीयू, एंगुलर, सॉलिड - यह सब अपरिहार्य है। चौखटे पर काम करते समय हमें जिन चीजों से जूझना पड़ता है उनमें से एक निम्न-स्तरीय UI घटकों को फिर से बनाना है: बटन, टैब, ड्रॉपडाउन, आदि। विशेष रूप से निराशाजनक बात यह है कि हम आम तौर पर उन्हें एक ढांचे में परिभाषित करेंगे। , रिएक्ट कहें, लेकिन फिर उन्हें फिर से लिखने की जरूरत है अगर हम Svelte में कुछ बनाना चाहते हैं। या व्यू। या ठोस। और इसी तरह।

क्या यह बेहतर नहीं होगा यदि हम इन निम्न-स्तरीय UI घटकों को एक बार ढांचे-अज्ञेय तरीके से परिभाषित कर सकें, और फिर उन्हें ढांचे के बीच पुन: उपयोग कर सकें? बेशक होगा! और हम कर सकते हैं; वेब घटक रास्ता हैं। यह पोस्ट आपको दिखाएगा कि कैसे।

अभी तक, वेब घटकों के लिए SSR कहानी में थोड़ी कमी है। डिक्लेरेटिव शैडो DOM (DSD) यह है कि कैसे एक वेब घटक सर्वर-साइड प्रदान किया जाता है, लेकिन, इस लेखन के रूप में, यह आपके पसंदीदा एप्लिकेशन फ्रेमवर्क जैसे नेक्स्ट, रीमिक्स या SvelteKit के साथ एकीकृत नहीं है। यदि यह आपके लिए आवश्यक है, तो DSD की नवीनतम स्थिति की जांच करना सुनिश्चित करें। लेकिन अन्यथा, यदि SSR वह नहीं है जिसका आप उपयोग कर रहे हैं, तो आगे पढ़ें।

पहला, कुछ संदर्भ

वेब घटक अनिवार्य रूप से HTML तत्व हैं जिन्हें आप स्वयं परिभाषित करते हैं, जैसे <yummy-pizza> या जो कुछ भी, जमीन से ऊपर। वे यहां सीएसएस-ट्रिक्स में शामिल हैं (सहित कालेब विलियम्स द्वारा एक व्यापक श्रृंखला और जॉन रिया द्वारा एक) लेकिन हम संक्षेप में इस प्रक्रिया पर चलेंगे। अनिवार्य रूप से, आप एक जावास्क्रिप्ट वर्ग को परिभाषित करते हैं, इसे इनहेरिट करते हैं HTMLElement, और फिर वेब घटक के जो भी गुण, विशेषताएँ और शैलियाँ हैं, उन्हें परिभाषित करें और निश्चित रूप से, यह मार्कअप अंततः आपके उपयोगकर्ताओं को प्रदान करेगा।

कस्टम HTML तत्वों को परिभाषित करने में सक्षम होना जो किसी विशेष घटक से बंधे नहीं हैं, रोमांचक है। लेकिन यह स्वतंत्रता भी एक सीमा है। किसी भी जावास्क्रिप्ट ढांचे से स्वतंत्र रूप से मौजूद होने का मतलब है कि आप वास्तव में उन जावास्क्रिप्ट ढांचे के साथ बातचीत नहीं कर सकते हैं। एक प्रतिक्रिया घटक के बारे में सोचें जो कुछ डेटा प्राप्त करता है और फिर कुछ प्रस्तुत करता है अन्य प्रतिक्रिया घटक, डेटा के साथ गुजर रहा है। यह वास्तव में एक वेब घटक के रूप में काम नहीं करेगा, क्योंकि एक वेब घटक नहीं जानता कि कैसे एक प्रतिक्रिया घटक प्रस्तुत करना है।

वेब घटक विशेष रूप से उत्कृष्ट हैं पत्ती घटक. पत्ता घटक एक घटक पेड़ में प्रदान की जाने वाली आखिरी चीज है। ये वे घटक हैं जो कुछ प्रॉप्स प्राप्त करते हैं, और कुछ प्रस्तुत करते हैं UI। य़े हैं नहीं आपके कंपोनेंट ट्री के बीच में बैठे हुए कंपोनेंट्स, साथ में डेटा पास करना, कॉन्टेक्स्ट सेट करना आदि — सिर्फ शुद्ध टुकड़े UI यह वही दिखेगा, इससे कोई फर्क नहीं पड़ता कि कौन सा जावास्क्रिप्ट ढांचा बाकी ऐप को शक्ति दे रहा है।

हम जिस वेब घटक का निर्माण कर रहे हैं

कुछ उबाऊ (और सामान्य) बनाने के बजाय, एक बटन की तरह, आइए कुछ अलग बनाते हैं। मेरे में पोस्ट लोड हो रहा है हमने सामग्री रीफ़्लो को रोकने के लिए धुंधली छवि पूर्वावलोकन का उपयोग करने पर ध्यान दिया, और हमारी छवियों के लोड होने पर उपयोगकर्ताओं के लिए एक अच्छा UI प्रदान किया। हमने बेस 64 को अपनी छवियों के धुंधले, खराब संस्करणों को कूटबद्ध करते हुए देखा, और यह दिखाते हुए कि हमारे UI में वास्तविक छवि लोड होने के दौरान। हमने एक टूल का उपयोग करके अविश्वसनीय रूप से कॉम्पैक्ट, धुंधली पूर्वावलोकन उत्पन्न करने पर भी ध्यान दिया ब्लरहाश.

उस पोस्ट ने आपको दिखाया कि उन पूर्वावलोकनों को कैसे उत्पन्न किया जाए और उन्हें एक प्रतिक्रिया परियोजना में उपयोग किया जाए। यह पोस्ट आपको दिखाएगा कि वेब घटक से उन पूर्वावलोकनों का उपयोग कैसे करें ताकि उनका उपयोग किया जा सके कोई जावास्क्रिप्ट ढांचा।

लेकिन हमें चलने से पहले चलने की जरूरत है, इसलिए हम पहले कुछ तुच्छ और मूर्खतापूर्ण तरीके से चलेंगे, यह देखने के लिए कि वेब घटक कैसे काम करते हैं।

इस पोस्ट में सब कुछ बिना किसी टूलिंग के वेनिला वेब घटकों का निर्माण करेगा। इसका मतलब है कि कोड में थोड़ा बॉयलरप्लेट होगा, लेकिन इसका पालन करना अपेक्षाकृत आसान होना चाहिए। जैसे उपकरण ज्योतिर्मय or स्टैंसिल वेब घटकों के निर्माण के लिए डिज़ाइन किए गए हैं और इस बॉयलरप्लेट को हटाने के लिए इसका उपयोग किया जा सकता है। मैं आपसे उनकी जांच करने का आग्रह करता हूं! लेकिन इस पोस्ट के लिए, मैं एक और निर्भरता को पेश करने और सिखाने के बदले में थोड़ा और बॉयलरप्लेट पसंद करूंगा।

एक साधारण काउंटर घटक

आइए जावास्क्रिप्ट घटकों के क्लासिक "हैलो वर्ल्ड" का निर्माण करें: एक काउंटर। हम एक मान और उस मान को बढ़ाने वाला एक बटन प्रस्तुत करेंगे। सरल और उबाऊ, लेकिन यह हमें सबसे सरल संभव वेब घटक को देखने देगा।

एक वेब घटक बनाने के लिए, पहला कदम एक जावास्क्रिप्ट वर्ग बनाना है, जो इससे प्राप्त होता है HTMLElement:

class Counter extends HTMLElement {}

अंतिम चरण वेब घटक को पंजीकृत करना है, लेकिन केवल तभी जब हमने इसे पहले से पंजीकृत नहीं किया है:

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

और, ज़ाहिर है, इसे प्रस्तुत करें:

<counter-wc></counter-wc>

और बीच में सब कुछ हम वेब घटक को वह कर रहे हैं जो हम चाहते हैं। एक सामान्य जीवनचक्र विधि है connectedCallback, जो तब सक्रिय होता है जब हमारे वेब घटक को DOM में जोड़ा जाता है। हम जो भी सामग्री चाहते हैं उसे प्रस्तुत करने के लिए हम उस विधि का उपयोग कर सकते हैं। याद रखें, यह एक जेएस वर्ग है जो विरासत में मिला है HTMLElement, जिसका अर्थ है हमारा this value वेब घटक तत्व ही है, सभी सामान्य DOM मैनिपुलेशन विधियों के साथ जिन्हें आप पहले से जानते हैं और पसंद करते हैं।

यह सबसे सरल है, हम यह कर सकते हैं:

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

... जो ठीक काम करेगा।

हरे रंग में "हे" शब्द।
इंटरऑपरेबल वेब घटकों का निर्माण जो प्रतिक्रिया के साथ भी काम करते हैं

वास्तविक सामग्री जोड़ना

आइए कुछ उपयोगी, इंटरैक्टिव सामग्री जोड़ें। हमे जरूरत है <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;
}

यह काम करता हैं!

काउंटर वेब घटक।
इंटरऑपरेबल वेब घटकों का निर्माण जो प्रतिक्रिया के साथ भी काम करते हैं

जाहिर है यह वह कोड नहीं है जिसे आप बड़े पैमाने पर बनाए रखना चाहते हैं। यहाँ एक पूर्ण है काम करने का उदाहरण अगर आप करीब से देखना चाहते हैं। जैसा कि मैंने कहा है, लिट और स्टैंसिल जैसे उपकरण इसे सरल बनाने के लिए डिज़ाइन किए गए हैं।

कुछ और कार्यक्षमता जोड़ना

यह पोस्ट वेब घटकों में गहरा गोता नहीं है। हम सभी एपीआई और जीवनचक्र को कवर नहीं करेंगे; हम कवर भी नहीं करेंगे छाया जड़ें या स्लॉट. उन विषयों पर अंतहीन सामग्री है। यहां मेरा लक्ष्य वास्तव में कुछ उपयोगी मार्गदर्शन के साथ-साथ कुछ रुचि जगाने के लिए एक अच्छा पर्याप्त परिचय प्रदान करना है का उपयोग लोकप्रिय जावास्क्रिप्ट ढांचे के साथ वेब घटक जिन्हें आप पहले से जानते हैं और पसंद करते हैं।

इसके लिए, आइए अपने काउंटर वेब घटक को थोड़ा बढ़ाएँ। आइए इसे स्वीकार करें a color विशेषता, प्रदर्शित होने वाले मान के रंग को नियंत्रित करने के लिए। और चलिए इसे भी स्वीकार करते हैं a increment संपत्ति, इसलिए इस वेब घटक के उपभोक्ता इसे एक बार में 2, 3, 4 तक बढ़ा सकते हैं। और इन राज्य परिवर्तनों को चलाने के लिए, आइए अपने नए काउंटर का उपयोग एक स्वेल्ट सैंडबॉक्स में करें - हम थोड़ी देर में प्रतिक्रिया प्राप्त करेंगे।

हम पहले की तरह उसी वेब घटक से शुरू करेंगे और एक रंग विशेषता जोड़ेंगे। किसी विशेषता को स्वीकार करने और प्रतिक्रिया देने के लिए हमारे वेब घटक को कॉन्फ़िगर करने के लिए, हम एक स्थिर जोड़ते हैं 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 हमारे अंतर्निहित वेब घटक उदाहरण पर। यहां कुछ खास नहीं है: यह वही है जो यह पहले से ही की विशेषताओं के लिए करता है कोई एचटीएमएल तत्व।

चीजें थोड़ी दिलचस्प हो जाती हैं 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 प्रतिक्रिया के साथ। 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 हमारे लिए वह सब लेगवर्क संभालती है। इसे इस डेमो में देखें। यह सभी जावास्क्रिप्ट ढांचे के लिए मानक व्यवहार है।

तो मैंने आपको वेब घटक के प्रोप को सेट करने का मैन्युअल तरीका क्यों दिखाया? दो कारण: यह समझना उपयोगी है कि ये चीजें कैसे काम करती हैं और, एक पल पहले, मैंने कहा था कि यह सभी जावास्क्रिप्ट ढांचे के लिए "बहुत ज्यादा" काम करता है। लेकिन एक ढांचा है, जो पागलपन से, वेब घटक प्रोप सेटिंग का समर्थन नहीं करता है जैसा कि हमने अभी देखा।

प्रतिक्रिया एक अलग जानवर है

इंटरऑपरेबल वेब घटकों का निर्माण जो रिएक्ट प्लेटोब्लॉकचेन डेटा इंटेलिजेंस के साथ भी काम करते हैं। लंबवत खोज. ऐ.
इंटरऑपरेबल वेब घटकों का निर्माण जो प्रतिक्रिया के साथ भी काम करते हैं

प्रतिक्रिया। ग्रह पर सबसे लोकप्रिय जावास्क्रिप्ट ढांचा वेब घटकों के साथ बुनियादी इंटरऑप का समर्थन नहीं करता है। यह एक प्रसिद्ध समस्या है जो प्रतिक्रिया के लिए अद्वितीय है। दिलचस्प बात यह है कि यह वास्तव में रिएक्ट की प्रायोगिक शाखा में तय किया गया है, लेकिन किसी कारण से इसे संस्करण 18 में विलय नहीं किया गया था। उस ने कहा, हम अभी भी कर सकते हैं इसकी प्रगति को ट्रैक करें. और आप इसे स्वयं आज़मा सकते हैं a लाइव डेमो.

समाधान, निश्चित रूप से, a . का उपयोग करना है 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: हर जगह विशेषताओं का उपयोग करें

हमारे पास गुण हैं। यदि आपने ऊपर दिए गए रिएक्ट डेमो पर क्लिक किया है, तो increment प्रॉप काम नहीं कर रहा था, लेकिन रंग सही ढंग से बदल गया। क्या हम सब कुछ विशेषताओं के साथ कोड नहीं कर सकते? दुख की बात है नहीं। विशेषता मान केवल तार हो सकते हैं। यह यहाँ काफी अच्छा है, और हम इस दृष्टिकोण के साथ कुछ दूर तक पहुँचने में सक्षम होंगे। नंबर पसंद हैं increment स्ट्रिंग से और में परिवर्तित किया जा सकता है। हम JSON को ऑब्जेक्ट्स को स्ट्रिंग/पार्स भी कर सकते हैं। लेकिन अंततः हमें एक फ़ंक्शन को वेब घटक में पास करने की आवश्यकता होगी, और उस समय हम विकल्पों से बाहर हो जाएंगे।

विकल्प 2: इसे लपेटें

एक पुरानी कहावत है कि आप कंप्यूटर विज्ञान में किसी भी समस्या को अप्रत्यक्ष स्तर (अप्रत्यक्ष के बहुत सारे स्तरों की समस्या को छोड़कर) जोड़कर हल कर सकते हैं। इन प्रॉप्स को सेट करने के लिए कोड काफी प्रेडिक्टेबल और सिंपल है। क्या होगा अगर हम इसे एक पुस्तकालय में छिपाते हैं? Lit . के पीछे के स्मार्ट लोग एक उपाय है. वेब घटक देने के बाद यह पुस्तकालय आपके लिए एक नया रिएक्ट घटक बनाता है, और इसके लिए आवश्यक गुणों की सूची बनाता है। चतुर होते हुए भी, मैं इस दृष्टिकोण का प्रशंसक नहीं हूं।

मैन्युअल रूप से बनाए गए रिएक्ट घटकों के लिए वेब घटकों की एक-से-एक मैपिंग करने के बजाय, जो मैं पसंद करता हूं वह है एक रिएक्ट कंपोनेंट जिसे हम अपना वेब कंपोनेंट पास करते हैं टैग नाम सेवा मेरे (counter-wc हमारे मामले में) - सभी विशेषताओं और गुणों के साथ - और इस घटक के लिए हमारे वेब घटक को प्रस्तुत करने के लिए, जोड़ें ref, फिर पता करें कि एक प्रोप क्या है और एक विशेषता क्या है। मेरी राय में यही आदर्श समाधान है। मुझे ऐसी लाइब्रेरी के बारे में पता नहीं है जो ऐसा करती है, लेकिन इसे बनाना आसान होना चाहिए। आइए इसे एक शॉट दें!

यह वह जगह है प्रयोग देख रहे हैं:

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

इस प्रकार हम एक गतिशील नाम के साथ प्रतिक्रिया में एक तत्व बनाते हैं। वास्तव में, यह वही है जो रिएक्ट सामान्य रूप से JSX को ट्रांसपाइल करता है। हमारे सभी डिव को में बदल दिया गया है createElement("div") कॉल। हमें आम तौर पर इस एपीआई को सीधे कॉल करने की आवश्यकता नहीं होती है, लेकिन जब हमें इसकी आवश्यकता होती है तो यह वहां होता है।

इसके अलावा, हम अपने घटक को पारित किए गए प्रत्येक प्रोप के माध्यम से एक लेआउट प्रभाव और लूप चलाना चाहते हैं। हम उन सभी के माध्यम से लूप करते हैं और यह देखने के लिए जांचते हैं कि यह एक संपत्ति है या नहीं in जांचें कि वेब घटक इंस्टेंस ऑब्जेक्ट के साथ-साथ इसकी प्रोटोटाइप श्रृंखला की जांच करता है, जो क्लास प्रोटोटाइप पर चलने वाले किसी भी गेटर्स/सेटर्स को पकड़ लेगा। यदि ऐसी कोई संपत्ति मौजूद नहीं है, तो इसे एक विशेषता माना जाता है। किसी भी मामले में, हम इसे केवल तभी सेट करते हैं जब मान वास्तव में बदल गया हो।

यदि आप सोच रहे हैं कि हम इसका उपयोग क्यों करते हैं useLayoutEffect के बजाय useEffect, ऐसा इसलिए है क्योंकि हम अपनी सामग्री के प्रस्तुत होने से पहले इन अद्यतनों को तुरंत चलाना चाहते हैं। साथ ही, ध्यान दें कि हमारे पास कोई निर्भरता सरणी नहीं है useLayoutEffect; इसका मतलब है कि हम इस अपडेट को चालू करना चाहते हैं हर रेंडर. यह जोखिम भरा हो सकता है क्योंकि रिएक्ट फिर से प्रस्तुत करने के लिए जाता है बहुत. मैं पूरी बात को लपेटकर इसे सुधारता हूं React.memo. यह अनिवार्य रूप से का आधुनिक संस्करण है React.PureComponent, जिसका अर्थ है कि घटक केवल तभी फिर से प्रस्तुत करेगा जब उसका कोई वास्तविक सहारा बदल गया हो - और यह जाँचता है कि क्या यह एक साधारण समानता जाँच के माध्यम से हुआ है।

यहां एकमात्र जोखिम यह है कि यदि आप किसी ऑब्जेक्ट प्रोप को पास कर रहे हैं जिसे आप बिना पुन: असाइन किए सीधे उत्परिवर्तित कर रहे हैं, तो आपको अपडेट दिखाई नहीं देंगे। लेकिन यह अत्यधिक हतोत्साहित किया जाता है, विशेष रूप से रिएक्ट समुदाय में, इसलिए मैं इसके बारे में चिंता नहीं करूंगा।

आगे बढ़ने से पहले, मैं एक आखिरी बात बताना चाहूंगा। हो सकता है कि आप इस बात से खुश न हों कि उपयोग कैसा दिखता है। फिर से, इस घटक का उपयोग इस तरह किया जाता है:

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

विशेष रूप से, हो सकता है कि आपको वेब घटक टैग नाम को पास करना पसंद न हो <WcWrapper> घटक और इसके बजाय पसंद करते हैं @lit-labs/react उपरोक्त पैकेज, जो प्रत्येक वेब घटक के लिए एक नया व्यक्तिगत प्रतिक्रिया घटक बनाता है। यह पूरी तरह से उचित है और मैं आपको उस चीज़ का उपयोग करने के लिए प्रोत्साहित करूंगा जिसमें आप सबसे अधिक सहज हों। लेकिन मेरे लिए, इस दृष्टिकोण के साथ एक फायदा यह है कि इसे करना आसान है हटाना. अगर किसी चमत्कार से रिएक्ट अपनी प्रायोगिक शाखा से उचित वेब कंपोनेंट हैंडलिंग को मर्ज कर देता है main कल, आप उपरोक्त कोड को इससे बदल सकेंगे:

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

…इसके लिए:

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

आप शायद हर जगह ऐसा करने के लिए एक भी कोडमॉड लिख सकते हैं, और फिर हटा सकते हैं <WcWrapper> पूरी तरह से। असल में, इसे स्क्रैच करें: एक वैश्विक खोज और एक RegEx के साथ प्रतिस्थापित करना शायद काम करेगा।

कार्यान्वयन

मुझे पता है, ऐसा लगता है कि यहां पहुंचने के लिए यात्रा करनी पड़ी। यदि आपको याद हो, तो हमारा मूल लक्ष्य उस छवि पूर्वावलोकन कोड को लेना था जिसे हमने my . में देखा था पोस्ट लोड हो रहा है, और इसे एक वेब घटक में ले जाएं ताकि इसका उपयोग किसी भी जावास्क्रिप्ट ढांचे में किया जा सके। रिएक्ट के उचित इंटरऑप की कमी ने मिश्रण में बहुत अधिक विवरण जोड़ा। लेकिन अब जब हमारे पास वेब घटक बनाने और उसका उपयोग करने के बारे में एक अच्छी समझ है, तो कार्यान्वयन लगभग जलवायु-विरोधी होगा।

मैं पूरे वेब घटक को यहां छोड़ दूंगा और कुछ दिलचस्प बिट्स को कॉल करूंगा। यदि आप इसे क्रिया में देखना चाहते हैं, तो यह है a काम कर रहे डेमो. यह मेरी तीन पसंदीदा प्रोग्रामिंग भाषाओं पर मेरी तीन पसंदीदा पुस्तकों के बीच स्विच करेगा। प्रत्येक पुस्तक का URL हर बार अद्वितीय होगा, इसलिए आप पूर्वावलोकन देख सकते हैं, हालांकि आप चीजों को वास्तव में घटित होते देखने के लिए अपने DevTools नेटवर्क टैब में चीजों को थ्रॉटल करना चाहेंगे।

पूरा कोड देखें
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;
}

आगे हमारे पास हमारी पूर्वावलोकन संपत्ति है, जो या तो हमारी बेस64 पूर्वावलोकन स्ट्रिंग हो सकती है, या हमारी 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); }
}

यदि हम इसे एक ढांचे में बनाते हैं तो यह हमारी आवश्यकता से थोड़ा अधिक बॉयलरप्लेट है, लेकिन उल्टा यह है कि हम इसे किसी भी ढांचे में फिर से उपयोग कर सकते हैं - हालांकि रिएक्ट को अभी के लिए एक रैपर की आवश्यकता होगी, जैसा कि हमने चर्चा की .

फुटकर चीज

मैंने पहले ही लिट के रिएक्ट रैपर का उल्लेख किया है। लेकिन अगर आप खुद को स्टैंसिल का उपयोग करते हुए पाते हैं, तो यह वास्तव में a . का समर्थन करता है सिर्फ प्रतिक्रिया के लिए अलग आउटपुट पाइपलाइन. और Microsoft के अच्छे लोगों के पास भी है लिट के रैपर के समान कुछ बनाया, फास्ट वेब घटक पुस्तकालय से जुड़ा हुआ है।

जैसा कि मैंने उल्लेख किया है, रिएक्ट नाम के सभी फ्रेमवर्क आपके लिए वेब कंपोनेंट प्रॉपर्टीज सेट करने का काम संभालेंगे। बस ध्यान दें कि कुछ में वाक्य रचना के कुछ विशेष स्वाद हैं। उदाहरण के लिए, सॉलिड.जेएस के साथ, <your-wc value={12}> हमेशा यही मानता है value एक संपत्ति है, जिसे आप a . से ओवरराइड कर सकते हैं attr उपसर्ग, जैसे <your-wc attr:value={12}>.

ऊपर लपेटकर

वेब घटक वेब विकास परिदृश्य का एक दिलचस्प, अक्सर कम उपयोग किया जाने वाला हिस्सा हैं। वे आपके UI, या "पत्ती" घटकों को प्रबंधित करके किसी एकल जावास्क्रिप्ट ढांचे पर आपकी निर्भरता को कम करने में मदद कर सकते हैं। वेब घटकों के रूप में इन्हें बनाते समय - स्वेल्ट या रिएक्ट घटकों के विपरीत - एर्गोनोमिक नहीं होगा, उल्टा यह है कि वे व्यापक रूप से पुन: प्रयोज्य होंगे।


इंटरऑपरेबल वेब घटकों का निर्माण जो प्रतिक्रिया के साथ भी काम करते हैं मूल रूप से प्रकाशित सीएसएस-ट्रिक्स। तुम्हे करना चाहिए समाचार पत्र प्राप्त करें.

समय टिकट:

से अधिक सीएसएस ट्रिक्स