इस कोडलैब (कोड बनाना सीखने के लिए ट्यूटोरियल) के बारे में जानकारी
1. परिचय
लिट क्या है
Lit, एक सामान्य लाइब्रेरी है. इसकी मदद से, कम साइज़ और तेज़ी से काम करने वाले ऐसे वेब कॉम्पोनेंट बनाए जा सकते हैं जो किसी भी फ़्रेमवर्क में या बिना किसी फ़्रेमवर्क के काम करते हैं. Lit की मदद से, शेयर किए जा सकने वाले कॉम्पोनेंट, ऐप्लिकेशन, डिज़ाइन सिस्टम वगैरह बनाए जा सकते हैं.
आप इन चीज़ों के बारे में जानेंगे
React के कई कॉन्सेप्ट का Lit में अनुवाद करने का तरीका. जैसे:
- JSX और टेंप्लेट बनाया जा रहा है
- कॉम्पोनेंट और प्रॉप्स
- राज्य & लाइफ़साइकल
- Hooks
- बच्चे
- रेफ़रंस
- मध्यस्थता स्थिति
आपको क्या बनाना होगा
इस कोडलैब के आखिर में, React कॉम्पोनेंट के सिद्धांतों को Lit ऐनालॉग में बदला जा सकेगा.
आपको इनकी ज़रूरत होगी
- Chrome, Safari, Firefox या Edge का सबसे नया वर्शन.
- एचटीएमएल, सीएसएस, JavaScript, और Chrome DevTools के बारे में जानकारी.
- प्रतिक्रिया का ज्ञान
- (बेहतर) अगर आपको डेवलपमेंट का सबसे अच्छा अनुभव चाहिए, तो वीएस कोड डाउनलोड करें. आपको वीएस कोड और एनपीएम के लिए लिट-प्लग इन की भी ज़रूरत होगी.
2. लिटर बनाम रिऐक्ट
Lit का मुख्य सिद्धांत और क्षमताएं, कई मायनों में React की तरह ही हैं. हालांकि, Lit में कुछ मुख्य अंतर हैं और ये उन्हें दूसरों से अलग बनाती हैं:
यह छोटा है
Lit छोटा है: React + ReactDOM के 40 से ज़्यादा केबी की तुलना में, इसमें करीब 5kb छोटा और gzip किया गया है.
यह तेज़ है
सार्वजनिक बेंचमार्क में, Lit के टेंप्लेट सिस्टम, lit-html की तुलना React के VDOM से की जाती है. सबसे खराब मामले में, React की तुलना में lit-html का इस्तेमाल 8-10% ज़्यादा और इस्तेमाल के सामान्य मामलों में 50%से ज़्यादा तेज़ होता है.
LitElement (Lit की कॉम्पोनेंट बेस क्लास), lit-html में बहुत कम ओवरहेड जोड़ती है. हालांकि, मेमोरी के इस्तेमाल, इंटरैक्शन, और स्टार्टअप समय जैसी कॉम्पोनेंट सुविधाओं की तुलना करने पर, React की परफ़ॉर्मेंस 16 से 30%तक कम हो जाती है.
बिल्ड की ज़रूरत नहीं है
ब्राउज़र की नई सुविधाओं, जैसे कि ES मॉड्यूल और टैग किए गए टेंप्लेट की लिटरल वैल्यू के साथ, Lit को चलाने के लिए कंपाइलेशन की ज़रूरत नहीं है. इसका मतलब है कि डेवलपर एनवायरमेंट को किसी स्क्रिप्ट टैग + ब्राउज़र + सर्वर के साथ सेट अप किया जा सकता है. साथ ही, इसे सेट अप किया जा सकता है और इस्तेमाल शुरू किया जा सकता है.
ES मॉड्यूल और नए ज़माने के सीडीएन, जैसे कि Skypack या UNPKG के साथ, हो सकता है कि शुरुआत करने के लिए आपको NPM की ज़रूरत न पड़े!
हालांकि, अगर आप चाहें, तो अब भी लिट कोड बनाया और ऑप्टिमाइज़ किया जा सकता है. नेटिव ES मॉड्यूल के बारे में हाल ही में डेवलपर, एक साथ मिलकर काम करता है. यह Lit के लिए अच्छा है – lit, सिर्फ़ एक सामान्य JavaScript है और इसके लिए किसी खास फ़्रेमवर्क के लिए सीएलआई या बिल्ड हैंडलिंग की ज़रूरत नहीं है.
फ़्रेमवर्क एग्नोस्टिक
ली के कॉम्पोनेंट, वेब कॉम्पोनेंट नाम के वेब स्टैंडर्ड का एक सेट बनाते हैं. इसका मतलब है कि Lit में एक कॉम्पोनेंट बनाने पर, मौजूदा और आने वाले समय के फ़्रेमवर्क पर काम किया जा सकेगा. अगर यह एचटीएमएल एलिमेंट के साथ काम करता है, तो यह वेब कॉम्पोनेंट के साथ काम करता है.
फ़्रेमवर्क इंटरऑप की समस्या सिर्फ़ तब होती है, जब फ़्रेमवर्क डीओएम के लिए सीमित तौर पर काम करते हैं. React इनमें से एक फ़्रेमवर्क है, लेकिन इसमें Refs की मदद से एस्केप करने की सुविधा मिलती है. साथ ही, Refs में Refs की मदद से डेवलपर को बेहतर अनुभव नहीं मिलता.
Lit की टीम, @lit-labs/react
नाम के एक एक्सपेरिमेंट पर काम कर रही है. यह प्रोजेक्ट, Lit के कॉम्पोनेंट अपने-आप पार्स करेगा और रिऐक्ट रैपर जनरेट करेगा. ऐसा इसलिए, ताकि आपको रेफ़रंस का इस्तेमाल न करना पड़े.
इसके अलावा, कस्टम एलिमेंट हर जगह आपको दिखाएगा कि कौनसे फ़्रेमवर्क और लाइब्रेरी, कस्टम एलिमेंट के साथ ठीक से काम करते हैं!
प्रथम-स्तरीय TypeScript समर्थन
हालांकि, आपके सभी Lit कोड को JavaScript में लिखना मुमकिन है, लेकिन Lit को TypeScript में लिखा गया है और Lit टीम का सुझाव है कि डेवलपर भी TypeScript का इस्तेमाल करें!
Lit टीम, Lit कम्यूनिटी के साथ मिलकर ऐसे प्रोजेक्ट को मैनेज करने में मदद कर रही है जो lit-analyzer
और lit-plugin
के साथ डेवलपमेंट और बिल्ड टाइम के दौरान TypeScript टाइप की जांच और Lit टेंप्लेट में इंटेलिजेंस को उपलब्ध कराते हैं.
डेवलपर टूल, ब्राउज़र में पहले से मौजूद होते हैं
लिट कॉम्पोनेंट, डीओएम में सिर्फ़ एचटीएमएल एलिमेंट होते हैं. इसका मतलब है कि अपने कॉम्पोनेंट की जांच करने के लिए, आपको अपने ब्राउज़र के लिए कोई भी टूल या एक्सटेंशन इंस्टॉल करने की ज़रूरत नहीं है.
आप बस डेवलपर टूल खोल सकते हैं, कोई एलीमेंट चुन सकते हैं और उसके गुण या स्थिति एक्सप्लोर कर सकते हैं.
इसे सर्वर साइड रेंडरिंग (एसएसआर) को ध्यान में रखकर बनाया गया है
Lit 2 को एसएसआर की सुविधा को ध्यान में रखकर बनाया गया है. कोडलैब के इस मॉड्यूल को लिखते समय, Lit टीम ने अभी SSR टूल को स्थिर रूप में रिलीज़ नहीं किया है, लेकिन Lit टीम पहले से ही Google के सभी प्रॉडक्ट में सर्वर साइड से रेंडर किए गए कॉम्पोनेंट को डिप्लॉय कर रही है और उन्होंने React ऐप्लिकेशन में एसएसआर की जांच कर ली है. Lit की टीम को उम्मीद है कि ये टूल जल्द ही GitHub पर उपलब्ध होंगे.
इस दौरान, लिटरेचर टीम की प्रोग्रेस के बारे में यहां जानें.
इसमें कम खरीदारी है
Lit को इस्तेमाल करने के लिए, ज़्यादा मेहनत नहीं करनी पड़ती! Lit में कॉम्पोनेंट बनाए जा सकते हैं और उन्हें अपने मौजूदा प्रोजेक्ट में जोड़ा जा सकता है. अगर आपको ये फ़ॉर्मैट पसंद नहीं हैं, तो आपको पूरे ऐप्लिकेशन को एक साथ बदलने की ज़रूरत नहीं है, क्योंकि वेब कॉम्पोनेंट दूसरे फ़्रेमवर्क में काम करते हैं!
क्या आपने Lit में पूरा ऐप्लिकेशन बनाया है और आपको उसमें कुछ और बदलना है? ठीक है, इसके बाद अपने मौजूदा Lit ऐप्लिकेशन को नए फ़्रेमवर्क के अंदर रखा जा सकता है. साथ ही, नए फ़्रेमवर्क के कॉम्पोनेंट में अपनी पसंद के मुताबिक डेटा माइग्रेट किया जा सकता है.
इसके अलावा, कई मॉडर्न फ़्रेमवर्क, वेब कॉम्पोनेंट में आउटपुट के साथ काम करते हैं. इसका मतलब है कि वे आम तौर पर, Lit एलिमेंट में खुद भी फ़िट हो सकते हैं.
3. सेट अप और प्लेग्राउंड को एक्सप्लोर करना
कोडलैब के इस मॉड्यूल को करने के दो तरीके हैं:
- आप इसे ब्राउज़र में पूरी तरह से ऑनलाइन कर सकते हैं
- (बेहतर) आप VS कोड का इस्तेमाल करके अपनी लोकल मशीन पर ऐसा कर सकते हैं
कोड ऐक्सेस करना
पूरे कोडलैब के दौरान, Lit के प्लेग्राउंड में इस तरह के लिंक दिखेंगे:
प्लेग्राउंड एक कोड सैंडबॉक्स होता है, जो आपके ब्राउज़र में पूरी तरह चलता है. यह TypeScript और JavaScript फ़ाइलों को कंपाइल और चला सकता है. साथ ही, यह नोड मॉड्यूल के इंपोर्ट को भी अपने-आप ठीक कर सकता है. उदाहरण के लिए,
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://cdn.skypack.dev/lit';
शुरुआती पॉइंट के तौर पर इन चेकपॉइंट का इस्तेमाल करके, Lit खेल के मैदान में पूरा ट्यूटोरियल किया जा सकता है. अगर आपने वीएस कोड का इस्तेमाल किया है, तो इन चेकपॉइंट का इस्तेमाल करके किसी भी चरण के लिए शुरुआती कोड डाउनलोड किया जा सकता है. साथ ही, इन चेकपॉइंट का इस्तेमाल करके अपने काम की जांच की जा सकती है.
रोशनी से जगमगाते प्लेग्राउंड यूआई को एक्सप्लोर करें
लिटिल प्लेग्राउंड यूज़र इंटरफ़ेस (यूआई) का स्क्रीनशॉट, उन सेक्शन को हाइलाइट करता है जिनका इस्तेमाल आपको इस कोडलैब में किया जाएगा.
- फ़ाइल चुनने वाला टूल. प्लस बटन को नोट करें...
- फ़ाइल संपादक.
- कोड की झलक.
- 'फिर से लोड करें' बटन.
- 'डाउनलोड करें' बटन.
बनाम कोड सेटअप (बेहतर)
बनाम इस बनाम कोड सेटअप का इस्तेमाल करने के फ़ायदे यहां दिए गए हैं:
- टेंप्लेट टाइप की जांच
- टेंप्लेट इंटेलिजेंस और अपने-आप पूरा होने की सुविधा
अगर आपके पास NPM, VS Code (lit-plugin प्लग इन के साथ) पहले से इंस्टॉल है और आपको उस एनवायरमेंट का इस्तेमाल करने का तरीका पता है, तो यहां दिए गए तरीके से इन प्रोजेक्ट को डाउनलोड करके शुरू किया जा सकता है:
- 'डाउनलोड करें' बटन दबाएं
- टार फ़ाइल के कॉन्टेंट को डायरेक्ट्री में निकालें
- (अगर टीएस है), तो एक क्विक tsconfig सेट अप करें, जो es मॉड्यूल और es2015+ का आउटपुट देता हो
- ऐसा डेव सर्वर इंस्टॉल करें जो बेयर मॉड्यूल स्पेसिफ़िकेशन का समाधान कर सके (लिट टीम @web/dev-server का सुझाव देती है)
- यहां एक उदाहरण दिया गया है
package.json
- यहां एक उदाहरण दिया गया है
- डेव सर्वर चलाएं और अपना ब्राउज़र खोलें (अगर @web/dev-server का इस्तेमाल किया जा रहा है, तो
npx web-dev-server --node-resolve --watch --open
का इस्तेमाल किया जा सकता है)- अगर आपने
package.json
का इस्तेमाल किया है, तोnpm run dev
का इस्तेमाल करें
- अगर आपने
4. JSX और टेंप्लेट बनाया जा रहा है
इस सेक्शन में, आपको Lit में टेंप्लेट बनाने की बुनियादी जानकारी मिलेगी.
JSX और लिट टेंप्लेट
JSX, JavaScript का एक सिंटैक्स एक्सटेंशन है. इसकी मदद से, React के उपयोगकर्ता अपने JavaScript कोड में आसानी से टेंप्लेट लिख सकते हैं. लिट टेंप्लेट का इस्तेमाल इसी तरह से किया जा सकता है: किसी कॉम्पोनेंट के यूज़र इंटरफ़ेस (यूआई) को उसकी स्थिति के फ़ंक्शन के तौर पर दिखाना.
बेसिक सिंटैक्स
React में, आपको एक JSX हैलो वर्ल्ड इस तरह रेंडर करना होगा:
import 'react';
import ReactDOM from 'react-dom';
const name = 'Josh Perez';
const element = (
<>
<h1>Hello, {name}</h1>
<div>How are you?</div>
</>
);
ReactDOM.render(
element,
mountNode
);
ऊपर दिए गए उदाहरण में, दो एलिमेंट हैं और एक "नाम" शामिल है वैरिएबल. लिट में आपको ये काम करने होंगे:
import {html, render} from 'lit';
const name = 'Josh Perez';
const element = html`
<h1>Hello, ${name}</h1>
<div>How are you?</div>`;
render(
element,
mountNode
);
ध्यान दें कि Lit टेंप्लेट को अपने टेंप्लेट में कई एलिमेंट का ग्रुप बनाने के लिए, React फ़्रैगमेंट की ज़रूरत नहीं है.
Lit में, टेंप्लेट को html
टैग किए गए टेंप्लेट LITeral के साथ रैप किया जाता है. इसमें Lit का नाम यहां पर दिया गया है!
टेम्प्लेट मान
लिटिल टेंप्लेट, TemplateResult
नाम के दूसरे Lit टेंप्लेट को स्वीकार कर सकते हैं. उदाहरण के लिए, name
को इटैलिक (<i>
) टैग में रैप करें और इसे टैग किए गए टेंप्लेट लिटरल N.B के साथ रैप करें.पक्का करें कि आपने सिंगल कोट वर्ण ('
) के बजाय बैकटिक वर्ण (`
) का इस्तेमाल किया हो.
import {html, render} from 'lit';
const name = html`<i>Josh Perez</i>`;
const element = html`
<h1>Hello, ${name}</h1>
<div>How are you?</div>`;
render(
element,
mountNode
);
लिट TemplateResult
, कलेक्शन, स्ट्रिंग, अन्य TemplateResult
, और डायरेक्टिव को भी स्वीकार कर सकता है.
कसरत के लिए, इस रिऐक्ट कोड को Lit में बदलें:
const itemsToBuy = [
<li>Bananas</li>,
<li>oranges</li>,
<li>apples</li>,
<li>grapes</li>
];
const element = (
<>
<h1>Things to buy:</h1>
<ol>
{itemsToBuy}
</ol>
</>);
ReactDOM.render(
element,
mountNode
);
जवाब:
import {html, render} from 'lit';
const itemsToBuy = [
html`<li>Bananas</li>`,
html`<li>oranges</li>`,
html`<li>apples</li>`,
html`<li>grapes</li>`
];
const element = html`
<h1>Things to buy:</h1>
<ol>
${itemsToBuy}
</ol>`;
render(
element,
mountNode
);
पासिंग और सेटिंग प्रॉप्स
JSX और Lit के सिंटैक्स में सबसे बड़ा अंतर, डेटा बाइंडिंग सिंटैक्स है. उदाहरण के लिए, बाइंडिंग के साथ इस प्रतिक्रिया इनपुट को लें:
const disabled = false;
const label = 'my label';
const myClass = 'my-class';
const value = 'my value';
const element =
<input
disabled={disabled}
className={`static-class ${myClass}`}
defaultValue={value}/>;
ReactDOM.render(
element,
mountNode
);
ऊपर दिए गए उदाहरण में, एक इनपुट तय किया गया है. इससे ये काम किए जाते हैं:
- किसी तय किए गए वैरिएबल पर सेट नहीं किया गया है (इस मामले में गलत)
- क्लास को
static-class
के साथ वैरिएबल (इस मामले में"static-class my-class"
) पर सेट करता है - डिफ़ॉल्ट वैल्यू सेट करता है
लिट में आपको ये काम करने होंगे:
import {html, render} from 'lit';
const disabled = false;
const label = 'my label';
const myClass = 'my-class';
const value = 'my value';
const element = html`
<input
?disabled=${disabled}
class="static-class ${myClass}"
.value=${value}>`;
render(
element,
mountNode
);
लिटिल उदाहरण में, disabled
एट्रिब्यूट को टॉगल करने के लिए एक बूलियन बाइंडिंग जोड़ी गई है.
इसके बाद, className
के बजाय सीधे class
एट्रिब्यूट से बाइंडिंग होती है. class
एट्रिब्यूट में एक से ज़्यादा बाइंडिंग जोड़ी जा सकती हैं. हालांकि, ऐसा सिर्फ़ तब होगा, जब classMap
डायरेक्टिव का इस्तेमाल न किया जा रहा हो. यह डायरेक्टिव, क्लास को टॉगल करने के लिए डिक्लेरेटिव हेल्पर है.
आखिर में, इनपुट पर value
प्रॉपर्टी सेट कर दी जाती है. React के उलट, इस सुविधा की मदद से इनपुट एलिमेंट को रीड-ओनली मोड पर सेट नहीं किया जा सकेगा, क्योंकि यह नेटिव लागू करने और इनपुट के व्यवहार के हिसाब से काम करता है.
लिट प्रॉप बाइंडिंग सिंटैक्स
html`<my-element ?attribute-name=${booleanVar}>`;
- किसी एलिमेंट पर एट्रिब्यूट को टॉगल करने के लिए,
?
प्रीफ़िक्स बाइंडिंग सिंटैक्स है inputRef.toggleAttribute('attribute-name', booleanVar)
के बराबरdisabled
का इस्तेमालdisabled="false"
के तौर पर करने वाले एलिमेंट के लिए मददगार है. इसे डीओएम अब भी सही मानता है, क्योंकिinputElement.hasAttribute('disabled') === true
html`<my-element .property-name=${anyVar}>`;
- किसी एलिमेंट की प्रॉपर्टी सेट करने के लिए,
.
प्रीफ़िक्स बाइंडिंग सिंटैक्स है inputRef.propertyName = anyVar
के बराबर- ऑब्जेक्ट, अरे या क्लास जैसे कॉम्प्लेक्स डेटा को पास करने के लिए सही है
html`<my-element attribute-name=${stringVar}>`;
- किसी एलिमेंट के एट्रिब्यूट से बाइंड करता है
inputRef.setAttribute('attribute-name', stringVar)
के बराबर- बेसिक वैल्यू, स्टाइल के नियम चुनने वाले टूल, और क्वेरी सिलेक्टर के लिए सही है
पासिंग हैंडलर
const disabled = false;
const label = 'my label';
const myClass = 'my-class';
const value = 'my value';
const element =
<input
onClick={() => console.log('click')}
onChange={e => console.log(e.target.value)} />;
ReactDOM.render(
element,
mountNode
);
ऊपर दिए गए उदाहरण में, एक इनपुट तय किया गया है. इससे ये काम किए जाते हैं:
- "क्लिक करें" शब्द लॉग करें इनपुट पर क्लिक करने पर
- जब उपयोगकर्ता कोई वर्ण टाइप करे, तब इनपुट की वैल्यू लॉग करें
लिट में आपको ये काम करने होंगे:
import {html, render} from 'lit';
const disabled = false;
const label = 'my label';
const myClass = 'my-class';
const value = 'my value';
const element = html`
<input
@click=${() => console.log('click')}
@input=${e => console.log(e.target.value)}>`;
render(
element,
mountNode
);
लिट के उदाहरण में, @click
वाले click
इवेंट में एक लिसनर जोड़ा गया है.
इसके बाद, onChange
का इस्तेमाल करने के बजाय, <input>
के नेटिव input
इवेंट के लिए बाइंडिंग है, क्योंकि नेटिव change
इवेंट सिर्फ़ blur
पर ट्रिगर होता है (इन इवेंट के बारे में ऐब्स्ट्रैक्ट प्रतिक्रिया दें).
लिटिल इवेंट हैंडलर सिंटैक्स
html`<my-element @event-name=${() => {...}}></my-element>`;
@
प्रीफ़िक्स किसी इवेंट लिसनर के लिए बाइंडिंग सिंटैक्स हैinputRef.addEventListener('event-name', ...)
के बराबर- नेटिव डीओएम इवेंट के नामों का इस्तेमाल करता है
5. कॉम्पोनेंट और प्रॉप्स
इस सेक्शन में, आपको लिटरेचर क्लास के कॉम्पोनेंट और फ़ंक्शन के बारे में जानकारी मिलेगी. राज्य और हुक के बारे में विस्तार से बाद के सेक्शन में बताया गया है.
क्लास कॉम्पोनेंट और LitElement
LitElement, Reऐक्टिव प्रॉपर्टी का सिद्धांत है. यह React क्लास के एक कॉम्पोनेंट के बराबर है React के सामान और उनकी स्थिति का मिला-जुला रूप है. उदाहरण के लिए:
import React from 'react';
import ReactDOM from 'react-dom';
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {name: ''};
}
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
const element = <Welcome name="Elliott"/>
ReactDOM.render(
element,
mountNode
);
ऊपर दिए गए उदाहरण में, एक React कॉम्पोनेंट है जो:
name
रेंडर करता हैname
की डिफ़ॉल्ट वैल्यू को खाली स्ट्रिंग (""
) पर सेट करता है- यह
name
,"Elliott"
को फिर से असाइन करता है
LitElement में ऐसा किया जा सकता है
TypeScript में:
import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';
@customElement('welcome-banner')
class WelcomeBanner extends LitElement {
@property({type: String})
name = '';
render() {
return html`<h1>Hello, ${this.name}</h1>`
}
}
JavaScript में:
import {LitElement, html} from 'lit';
class WelcomeBanner extends LitElement {
static get properties() {
return {
name: {type: String}
}
}
constructor() {
super();
this.name = '';
}
render() {
return html`<h1>Hello, ${this.name}</h1>`
}
}
customElements.define('welcome-banner', WelcomeBanner);
और एचटीएमएल फ़ाइल में:
<!-- index.html -->
<head>
<script type="module" src="./index.js"></script>
</head>
<body>
<welcome-banner name="Elliott"></welcome-banner>
</body>
ऊपर दिए गए उदाहरण में बताई गई वजह की समीक्षा:
@property({type: String})
name = '';
- सार्वजनिक प्रतिक्रियाशील प्रॉपर्टी के बारे में बताता है – यह आपके कॉम्पोनेंट के सार्वजनिक एपीआई का हिस्सा होता है
- यह आपके कॉम्पोनेंट पर डिफ़ॉल्ट रूप से, एक एट्रिब्यूट के साथ-साथ एक प्रॉपर्टी दिखाता है
- यह बताता है कि कॉम्पोनेंट के एट्रिब्यूट (जो कि स्ट्रिंग हैं) को वैल्यू में कैसे बदला जाता है
static get properties() {
return {
name: {type: String}
}
}
- यह
@property
TS डेकोरेटर की तरह ही काम करता है, लेकिन JavaScript में मूल रूप से चलता है
render() {
return html`<h1>Hello, ${this.name}</h1>`
}
- जब भी कोई रिऐक्टिव प्रॉपर्टी बदली जाती है, तो इसे कॉल किया जाता है
@customElement('welcome-banner')
class WelcomeBanner extends LitElement {
...
}
- यह एचटीएमएल एलिमेंट टैग के नाम को क्लास की परिभाषा से जोड़ता है
- कस्टम एलिमेंट स्टैंडर्ड की वजह से, टैग के नाम में हाइफ़न (-) शामिल होना चाहिए
- LitElement में
this
, कस्टम एलिमेंट के इंस्टेंस का हवाला देता है (इस मामले में<welcome-banner>
)
customElements.define('welcome-banner', WelcomeBanner);
- यह
@customElement
टीएस डेकोरेटर का JavaScript जैसा है
<head>
<script type="module" src="./index.js"></script>
</head>
- कस्टम एलिमेंट की परिभाषा को इंपोर्ट करता है
<body>
<welcome-banner name="Elliott"></welcome-banner>
</body>
- पेज में कस्टम एलिमेंट जोड़ता है
- यह
name
प्रॉपर्टी को'Elliott'
पर सेट करता है
फ़ंक्शन कॉम्पोनेंट
Lit में फ़ंक्शन कॉम्पोनेंट का 1:1 मतलब नहीं है, क्योंकि यह JSX या प्रीप्रोसेसर का इस्तेमाल नहीं करता. हालांकि, ऐसा फ़ंक्शन कंपोज़ करना आसान है जो प्रॉपर्टी को लेता है और उन प्रॉपर्टी के आधार पर डीओएम को रेंडर करता है. उदाहरण के लिए:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Elliott"/>
ReactDOM.render(
element,
mountNode
);
लिट में यह होगा:
import {html, render} from 'lit';
function Welcome(props) {
return html`<h1>Hello, ${props.name}</h1>`;
}
render(
Welcome({name: 'Elliott'}),
document.body.querySelector('#root')
);
6. राज्य & लाइफ़साइकल
इस सेक्शन में, लिटरेचर की स्थिति और लाइफ़साइकल के बारे में बताया गया है.
स्थिति
"रिऐक्टिव प्रॉपर्टी" का सिद्धांत रिऐक्ट की स्थिति और प्रॉप्स का मिला-जुला रूप है. रिऐक्टिव प्रॉपर्टी को बदलने पर, कॉम्पोनेंट का लाइफ़साइकल ट्रिगर हो सकता है. रिऐक्टिव प्रॉपर्टी दो वैरिएंट में आती हैं:
पब्लिक रिऐक्टिव प्रॉपर्टी
// React
import React from 'react';
class MyEl extends React.Component {
constructor(props) {
super(props)
this.state = {name: 'there'}
}
componentWillReceiveProps(nextProps) {
if (this.props.name !== nextProps.name) {
this.setState({name: nextProps.name})
}
}
}
// Lit (TS)
import {LitElement} from 'lit';
import {property} from 'lit/decorators.js';
class MyEl extends LitElement {
@property() name = 'there';
}
@property
ने तय किया- React के प्रॉप्स और स्टेट की तरह, लेकिन बदलाव किया जा सकता है
- ऐसा सार्वजनिक एपीआई जिसे कॉम्पोनेंट के उपभोक्ता ऐक्सेस और सेट करते हैं
इंटरनल रिऐक्टिव स्टेट
// React
import React from 'react';
class MyEl extends React.Component {
constructor(props) {
super(props)
this.state = {name: 'there'}
}
}
// Lit (TS)
import {LitElement} from 'lit';
import {state} from 'lit/decorators.js';
class MyEl extends LitElement {
@state() name = 'there';
}
@state
ने तय किया- React की स्थिति के जैसे, लेकिन बदला जा सकता है
- निजी इंटरनल स्थिति, जिसे आम तौर पर कॉम्पोनेंट या सब-क्लास से ऐक्सेस किया जाता है
जीवनचक्र
Lit लाइफ़साइकल काफ़ी मिलता-जुलता है, लेकिन इसमें कुछ बड़े अंतर हैं.
constructor
// React (js)
import React from 'react';
class MyEl extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this._privateProp = 'private';
}
}
// Lit (ts)
class MyEl extends LitElement {
@property({type: Number}) counter = 0;
private _privateProp = 'private';
}
// Lit (js)
class MyEl extends LitElement {
static get properties() {
return { counter: {type: Number} }
}
constructor() {
this.counter = 0;
this._privateProp = 'private';
}
}
- लिटरल वैल्यू भी
constructor
है - सुपर कॉल में कुछ भी भेजने की ज़रूरत नहीं है
- इन्होंने शुरू किया (पूरी तरह से शामिल नहीं है):
document.createElement
document.innerHTML
new ComponentClass()
- अगर पेज पर, अपग्रेड नहीं किए गए किसी टैग का नाम मौजूद है और डेफ़िनिशन लोड हो गई है और उसे
@customElement
याcustomElements.define
के साथ रजिस्टर किया गया है
- रिऐक्ट के
constructor
के फ़ंक्शन में मिलता-जुलता
render
// React
render() {
return <div>Hello World</div>
}
// Lit
render() {
return html`<div>Hello World</div>`;
}
- लिटरल वैल्यू भी
render
है - कोई भी रेंडर किया जा सकने वाला नतीजा दिखा सकता है, जैसे कि
TemplateResult
याstring
वगैरह. - React की तरह ही,
render()
भी पूरी तरह से फ़ंक्शन होना चाहिए - उस नोड में रेंडर किया जाएगा जिसे
createRenderRoot()
, डिफ़ॉल्ट रूप सेShadowRoot
दिखाता है
componentDidMount
componentDidMount
, Lit के firstUpdated
और connectedCallback
लाइफ़साइकल कॉलबैक, दोनों के कॉम्बिनेशन की तरह होता है.
firstUpdated
import Chart from 'chart.js';
// React
componentDidMount() {
this._chart = new Chart(this.chartElRef.current, {...});
}
// Lit
firstUpdated() {
this._chart = new Chart(this.chartEl, {...});
}
- इसे पहली बार तब कॉल किया जाता है, जब कॉम्पोनेंट के टेंप्लेट को कॉम्पोनेंट के रूट में रेंडर किया जाता है
- तभी कॉल किया जाएगा, जब एलिमेंट कनेक्ट किया गया हो, उदाहरण के लिए
document.createElement('my-component')
के ज़रिए तब तक कॉल नहीं किया जाता, जब तक कि उस नोड को डीओएम ट्री में नहीं जोड़ा जाता - यह कॉम्पोनेंट सेटअप करने के लिए एक अच्छी जगह है. इसके लिए, कॉम्पोनेंट के डीओएम की ज़रूरत होती है
firstUpdated
की रिऐक्टिव प्रॉपर्टी में React केcomponentDidMount
बदलाव से अलग, फिर से रेंडर होगा. हालांकि, ब्राउज़र आम तौर पर बदलावों को एक ही फ़्रेम में बैच बनाकर देगा. अगर इन बदलावों को रूट के डीओएम के ऐक्सेस की ज़रूरत नहीं है, तो आम तौर पर उन्हेंwillUpdate
में जाना चाहिए
connectedCallback
// React
componentDidMount() {
this.window.addEventListener('resize', this.boundOnResize);
}
// Lit
connectedCallback() {
super.connectedCallback();
this.window.addEventListener('resize', this.boundOnResize);
}
- जब कस्टम एलिमेंट को डीओएम ट्री में डाला जाता है, तब यह कॉल किया जाता है
- React कॉम्पोनेंट से अलग, जब कस्टम एलिमेंट डीओएम से अलग किए जाते हैं, तो उन्हें खत्म नहीं किया जाता. इसलिए, वे "कनेक्ट" हो सकते हैं एकाधिक बार
firstUpdated
को फिर से कॉल नहीं किया जाएगा
- इससे डीओएम को फिर से शुरू करने में मदद मिलती है. इसके अलावा, डिसकनेक्ट करने पर खाली किए गए इवेंट लिसनर को फिर से अटैच करने में मदद मिलती है
- ध्यान दें:
connectedCallback
कोfirstUpdated
से पहले कॉल किया जा सकता है, इसलिए पहली कॉल पर DOM उपलब्ध नहीं हो सकता है
componentDidUpdate
// React
componentDidUpdate(prevProps) {
if (this.props.title !== prevProps.title) {
this._chart.setTitle(this.props.title);
}
}
// Lit (ts)
updated(prevProps: PropertyValues<this>) {
if (prevProps.has('title')) {
this._chart.setTitle(this.title);
}
}
- अंग्रेज़ी के छोटे से "अपडेट" काल का इस्तेमाल करके,
updated
इसके बराबर है - React के उलट,
updated
को शुरुआती रेंडर पर भी कॉल किया जाता है - रिऐक्ट के
componentDidUpdate
के फ़ंक्शन में मिलता-जुलता
componentWillUnmount
// React
componentWillUnmount() {
this.window.removeEventListener('resize', this.boundOnResize);
}
// Lit
disconnectedCallback() {
super.disconnectedCallback();
this.window.removeEventListener('resize', this.boundOnResize);
}
- लिटरल वैल्यू
disconnectedCallback
से मिलती-जुलती है - रिऐक्ट कॉम्पोनेंट के उलट, जब कस्टम एलिमेंट को डीओएम से अलग किया जाता है, तो कॉम्पोनेंट खत्म नहीं होता
componentWillUnmount
के उलट, एलिमेंट को ट्री से हटाने के बादdisconnectedCallback
को कहा जाता है- रूट के अंदर का DOM अब भी रूट की सबट्री से जुड़ा है
- यह इवेंट लिसनर और लीक रेफ़रंस को हटाने में मदद करता है, ताकि ब्राउज़र, कॉम्पोनेंट के कलेक्शन को खराब कर सके
कसरत
import React from 'react';
import ReactDOM from 'react-dom';
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
ऊपर दिए गए उदाहरण में, एक सामान्य घड़ी मौजूद है, जो ये काम करती है:
- इससे "नमस्ते वर्ल्ड! यह है" और फिर समय दिखाता है
- हर सेकंड, घड़ी का समय अपडेट हो जाएगा
- अलग करने पर, यह टिक को कॉल करने वाले इंटरवल को हटा देता है
सबसे पहले कॉम्पोनेंट क्लास का एलान करें:
// Lit (TS)
// some imports here are imported in advance
import {LitElement, html} from 'lit';
import {customElement, state} from 'lit/decorators.js';
@customElement('lit-clock')
class LitClock extends LitElement {
}
// Lit (JS)
// `html` is imported in advance
import {LitElement, html} from 'lit';
class LitClock extends LitElement {
}
customElements.define('lit-clock', LitClock);
इसके बाद, date
को शुरू करें और इसे @state
के साथ इंटरनल रिऐक्टिव प्रॉपर्टी का एलान करें, क्योंकि कॉम्पोनेंट के उपयोगकर्ता date
को सीधे सेट नहीं करेंगे.
// Lit (TS)
import {LitElement, html} from 'lit';
import {customElement, state} from 'lit/decorators.js';
@customElement('lit-clock')
class LitClock extends LitElement {
@state() // declares internal reactive prop
private date = new Date(); // initialization
}
// Lit (JS)
import {LitElement, html} from 'lit';
class LitClock extends LitElement {
static get properties() {
return {
// declares internal reactive prop
date: {state: true}
}
}
constructor() {
super();
// initialization
this.date = new Date();
}
}
customElements.define('lit-clock', LitClock);
इसके बाद, टेंप्लेट रेंडर करें.
// Lit (JS & TS)
render() {
return html`
<div>
<h1>Hello, World!</h1>
<h2>It is ${this.date.toLocaleTimeString()}.</h2>
</div>
`;
}
अब, सही के निशान वाला तरीका लागू करें.
tick() {
this.date = new Date();
}
इसके बाद, componentDidMount
को लागू करने की ज़रूरत है. फिर से बता दें कि Lit ऐनालॉग firstUpdated
और connectedCallback
का मिला-जुला रूप है. इस कॉम्पोनेंट के मामले में, tick
को setInterval
के साथ कॉल करने के लिए, रूट के अंदर के DOM को ऐक्सेस करने की ज़रूरत नहीं होती. इसके अलावा, दस्तावेज़ ट्री से एलिमेंट को हटाने पर इंटरवल भी मिट जाएगा. इसलिए, अगर इसे फिर से अटैच किया जाता है, तो इंटरवल फिर से शुरू होगा. इसलिए, connectedCallback
यहां एक बेहतर विकल्प है.
// Lit (TS)
@customElement('lit-clock')
class LitClock extends LitElement {
@state()
private date = new Date();
// initialize timerId for TS
private timerId = -1 as unknown as ReturnType<typeof setTimeout>;
connectedCallback() {
super.connectedCallback();
this.timerId = setInterval(
() => this.tick(),
1000
);
}
...
}
// Lit (JS)
constructor() {
super();
// initialization
this.date = new Date();
this.timerId = -1; // initialize timerId for JS
}
connectedCallback() {
super.connectedCallback();
this.timerId = setInterval(
() => this.tick(),
1000
);
}
आखिर में, इंटरवल को साफ़ करें, ताकि एलिमेंट के दस्तावेज़ ट्री से डिसकनेक्ट होने के बाद, यह टिक न करे.
// Lit (TS & JS)
disconnectedCallback() {
super.disconnectedCallback();
clearInterval(this.timerId);
}
सभी को एक साथ रखें, तो यह कुछ ऐसा दिखना चाहिए:
// Lit (TS)
import {LitElement, html} from 'lit';
import {customElement, state} from 'lit/decorators.js';
@customElement('lit-clock')
class LitClock extends LitElement {
@state()
private date = new Date();
private timerId = -1 as unknown as ReturnType<typeof setTimeout>;
connectedCallback() {
super.connectedCallback();
this.timerId = setInterval(
() => this.tick(),
1000
);
}
tick() {
this.date = new Date();
}
render() {
return html`
<div>
<h1>Hello, World!</h1>
<h2>It is ${this.date.toLocaleTimeString()}.</h2>
</div>
`;
}
disconnectedCallback() {
super.disconnectedCallback();
clearInterval(this.timerId);
}
}
// Lit (JS)
import {LitElement, html} from 'lit';
class LitClock extends LitElement {
static get properties() {
return {
date: {state: true}
}
}
constructor() {
super();
this.date = new Date();
}
connectedCallback() {
super.connectedCallback();
this.timerId = setInterval(
() => this.tick(),
1000
);
}
tick() {
this.date = new Date();
}
render() {
return html`
<div>
<h1>Hello, World!</h1>
<h2>It is ${this.date.toLocaleTimeString()}.</h2>
</div>
`;
}
disconnectedCallback() {
super.disconnectedCallback();
clearInterval(this.timerId);
}
}
customElements.define('lit-clock', LitClock);
7. Hooks
इस सेक्शन में आपको React Hook के कॉन्सेप्ट को Lit में बदलने का तरीका पता चलेगा.
रिऐक्ट हुक के सिद्धांत
रिऐक्ट हुक, फ़ंक्शन कॉम्पोनेंट को "हुक" में बदलने का तरीका बताते हैं राज्य के हिसाब से बनाया गया है. इसके कई फ़ायदे हैं.
- ये स्टेटफ़ुल लॉजिक के फिर से इस्तेमाल को आसान बनाते हैं
- कॉम्पोनेंट को छोटे-छोटे फ़ंक्शन में बांटने में मदद करता है
इसके अलावा, फ़ंक्शन पर आधारित कॉम्पोनेंट पर फ़ोकस करने से, React के क्लास-आधारित सिंटैक्स से जुड़ी कुछ समस्याओं का पता चला. जैसे:
props
कोconstructor
सेsuper
में पास करना होगाconstructor
- में प्रॉपर्टी का सही से शुरू होना
- उस समय React टीम ने इसी वजह से इसे हल कर लिया था, लेकिन ES2019 ने इसे हल कर दिया
this
की वजह से हुई समस्याएं, अब कॉम्पोनेंट से जुड़ी नहीं हैं
लिटरेचर हुक के कॉन्सेप्ट पर प्रतिक्रिया दें
जैसा कि कॉम्पोनेंट & प्रॉप्स सेक्शन में, Lit में फ़ंक्शन से कस्टम एलिमेंट बनाने की सुविधा नहीं है. हालांकि, LitElement ने React क्लास के कॉम्पोनेंट की ज़्यादातर मुख्य समस्याओं को हल करने का विकल्प दिया है. उदाहरण के लिए:
// React (at the time of making hooks)
import React from 'react';
import ReactDOM from 'react-dom';
class MyEl extends React.Component {
constructor(props) {
super(props); // Leaky implementation
this.state = {count: 0};
this._chart = null; // Deemed messy
}
render() {
return (
<>
<div>Num times clicked {count}</div>
<button onClick={this.clickCallback}>click me</button>
</>
);
}
clickCallback() {
// Errors because `this` no longer refers to the component
this.setState({count: this.count + 1});
}
}
// Lit (ts)
class MyEl extends LitElement {
@property({type: Number}) count = 0; // No need for constructor to set state
private _chart = null; // Public class fields introduced to JS in 2019
render() {
return html`
<div>Num times clicked ${count}</div>
<button @click=${this.clickCallback}>click me</button>`;
}
private clickCallback() {
// No error because `this` refers to component
this.count++;
}
}
Lit इन समस्याओं को कैसे हल करता है?
constructor
कोई तर्क नहीं लेता- सभी
@event
बाइंडिंग,this
से अपने-आप बाइंड हो जाती हैं - ज़्यादातर मामलों में
this
, कस्टम एलिमेंट के रेफ़रंस को दिखाता है - क्लास की प्रॉपर्टी को अब क्लास के सदस्यों के तौर पर इंस्टैंशिएट किया जा सकता है. इससे कंस्ट्रक्टर-आधारित तरीकों का इस्तेमाल करना आसान हो जाता है
रिऐक्टिव कंट्रोलर
हुक के पीछे के मुख्य सिद्धांत, Lit में रिऐक्टिव कंट्रोलर के तौर पर मौजूद हैं. रिऐक्टिव कंट्रोलर पैटर्न से, स्टेटफ़ुल लॉजिक को शेयर किया जा सकता है. साथ ही, कॉम्पोनेंट को छोटे और ज़्यादा मॉड्यूलर बिट में बांटा जा सकता है. साथ ही, एलिमेंट के अपडेट लाइफ़साइकल में हुक किया जा सकता है.
रिऐक्टिव कंट्रोलर एक ऐसा ऑब्जेक्ट इंटरफ़ेस है जो LitElement जैसे कंट्रोलर होस्ट के अपडेट लाइफ़साइकल का हिस्सा बना सकता है.
ReactiveController
और reactiveControllerHost
की लाइफ़साइकल है:
interface ReactiveController {
hostConnected(): void;
hostUpdate(): void;
hostUpdated(): void;
hostDisconnected(): void;
}
interface ReactiveControllerHost {
addController(controller: ReactiveController): void;
removeController(controller: ReactiveController): void;
requestUpdate(): void;
readonly updateComplete: Promise<boolean>;
}
एक रिऐक्टिव कंट्रोलर बनाकर और उसे addController
के साथ किसी होस्ट से अटैच करने पर, कंट्रोलर के लाइफ़साइकल को होस्ट के साथ कॉल किया जाएगा. उदाहरण के लिए, राज्य और लाइफ़साइकल सेक्शन:
import React from 'react';
import ReactDOM from 'react-dom';
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
ऊपर दिए गए उदाहरण में, एक सामान्य घड़ी ये काम करती है:
- इससे "नमस्ते वर्ल्ड! यह है" और फिर समय दिखाता है
- हर सेकंड, घड़ी का समय अपडेट हो जाएगा
- अलग करने पर, यह टिक को कॉल करने वाले इंटरवल को हटा देता है
कॉम्पोनेंट बनाने का तरीका
सबसे पहले कॉम्पोनेंट क्लास का एलान करना शुरू करें और फिर render
फ़ंक्शन जोड़ें.
// Lit (TS) - index.ts
import {LitElement, html} from 'lit';
import {customElement} from 'lit/decorators.js';
@customElement('my-element')
class MyElement extends LitElement {
render() {
return html`
<div>
<h1>Hello, world!</h1>
<h2>It is ${'time to get Lit'}.</h2>
</div>
`;
}
}
// Lit (JS) - index.js
import {LitElement, html} from 'lit';
class MyElement extends LitElement {
render() {
return html`
<div>
<h1>Hello, world!</h1>
<h2>It is ${'time to get Lit'}.</h2>
</div>
`;
}
}
customElements.define('my-element', MyElement);
कंट्रोलर बनाना
अब clock.ts
पर स्विच करें और ClockController
के लिए क्लास बनाएं और constructor
सेट अप करें:
// Lit (TS) - clock.ts
import {ReactiveController, ReactiveControllerHost} from 'lit';
export class ClockController implements ReactiveController {
private readonly host: ReactiveControllerHost;
constructor(host: ReactiveControllerHost) {
this.host = host;
host.addController(this);
}
hostConnected() {
}
private tick() {
}
hostDisconnected() {
}
}
// Lit (JS) - clock.js
export class ClockController {
constructor(host) {
this.host = host;
host.addController(this);
}
hostConnected() {
}
tick() {
}
hostDisconnected() {
}
}
रिऐक्टिव कंट्रोलर को किसी भी तरीके से तब तक बनाया जा सकता है, जब तक वह ReactiveController
इंटरफ़ेस शेयर करता है. हालांकि, वह क्लास constructor
वाली क्लास का इस्तेमाल करके बनाया जा सकता है जो ReactiveControllerHost
इंटरफ़ेस को अपना सकती है. साथ ही, कंट्रोलर को शुरू करने के लिए ज़रूरी किसी दूसरी प्रॉपर्टी का इस्तेमाल करके, Lit टीम ज़्यादातर बुनियादी मामलों में इसे इस्तेमाल करना पसंद करती है.
अब आपको React लाइफ़साइकल कॉलबैक को कंट्रोलर कॉलबैक में बदलना होगा. कम शब्दों में कहें:
componentDidMount
- LitElement के
connectedCallback
पर - कंट्रोलर के
hostConnected
में
- LitElement के
ComponentWillUnmount
- LitElement के
disconnectedCallback
पर - कंट्रोलर के
hostDisconnected
में
- LitElement के
रिऐक्ट लाइफ़साइकल को लिटिल लाइफ़साइकल में अनुवाद करने के बारे में ज़्यादा जानकारी के लिए, स्टेट और लाइफ़साइकल सेक्शन.
इसके बाद, hostConnected
कॉलबैक और tick
मेथड लागू करें और hostDisconnected
में इंटरवल को साफ़ करें, जैसा कि राज्य और लाइफ़साइकल सेक्शन.
// Lit (TS) - clock.ts
export class ClockController implements ReactiveController {
private readonly host: ReactiveControllerHost;
private interval = 0 as unknown as ReturnType<typeof setTimeout>;
date = new Date();
constructor(host: ReactiveControllerHost) {
this.host = host;
host.addController(this);
}
hostConnected() {
this.interval = setInterval(() => this.tick(), 1000);
}
private tick() {
this.date = new Date();
}
hostDisconnected() {
clearInterval(this.interval);
}
}
// Lit (JS) - clock.js
export class ClockController {
interval = 0;
host;
date = new Date();
constructor(host) {
this.host = host;
host.addController(this);
}
hostConnected() {
this.interval = setInterval(() => this.tick(), 1000);
}
tick() {
this.date = new Date();
}
hostDisconnected() {
clearInterval(this.interval);
}
}
कंट्रोलर का इस्तेमाल करना
क्लॉक कंट्रोलर का इस्तेमाल करने के लिए, कंट्रोलर को इंपोर्ट करें. इसके बाद, index.ts
या index.js
में कॉम्पोनेंट को अपडेट करें.
// Lit (TS) - index.ts
import {LitElement, html, ReactiveController, ReactiveControllerHost} from 'lit';
import {customElement} from 'lit/decorators.js';
import {ClockController} from './clock.js';
@customElement('my-element')
class MyElement extends LitElement {
private readonly clock = new ClockController(this); // Instantiate
render() {
// Use controller
return html`
<div>
<h1>Hello, world!</h1>
<h2>It is ${this.clock.date.toLocaleTimeString()}.</h2>
</div>
`;
}
}
// Lit (JS) - index.js
import {LitElement, html} from 'lit';
import {ClockController} from './clock.js';
class MyElement extends LitElement {
clock = new ClockController(this); // Instantiate
render() {
// Use controller
return html`
<div>
<h1>Hello, world!</h1>
<h2>It is ${this.clock.date.toLocaleTimeString()}.</h2>
</div>
`;
}
}
customElements.define('my-element', MyElement);
नियंत्रक का इस्तेमाल करने के लिए, आपको नियंत्रक होस्ट (जो कि <my-element>
घटक है) के रेफ़रंस में पास करके नियंत्रक को इंस्टैंशिएट करना होगा. इसके बाद, नियंत्रक को render
तरीके में इस्तेमाल करना होगा.
कंट्रोलर में फिर से रेंडर करना ट्रिगर करना
ध्यान दें कि इसमें समय दिखाया जाएगा, लेकिन समय अपडेट नहीं हो रहा है. ऐसा इसलिए है, क्योंकि कंट्रोलर हर सेकंड में तारीख सेट कर रहा है, लेकिन होस्ट अपडेट नहीं हो रहा है. इसकी वजह यह है कि date
अब ClockController
क्लास में बदल रहा है, कॉम्पोनेंट में नहीं. इसका मतलब है कि कंट्रोलर पर date
को सेट करने के बाद, होस्ट को host.requestUpdate()
के साथ, अपने अपडेट की लाइफ़साइकल चलाने के लिए कहा जाना चाहिए.
// Lit (TS & JS) - clock.ts / clock.js
private tick() {
this.date = new Date();
this.host.requestUpdate();
}
अब समय निकल रहा होगा!
हुक के साथ सामान्य इस्तेमाल के उदाहरणों की ज़्यादा गहराई से तुलना करने के लिए, कृपया बेहतर विषय - हुक सेक्शन देखें.
8. बच्चे
इस सेक्शन में, आपको लिटरेचर में बच्चों को मैनेज करने के लिए स्लॉट इस्तेमाल करने का तरीका बताया जाएगा.
स्लॉट और बच्चे
स्लॉट, कॉम्पोनेंट को नेस्ट करके कंपोज़िशन को चालू करते हैं.
प्रतिक्रिया में, बच्चों को चीज़ों से मिलती-जुलती चीज़ें मिलती हैं. डिफ़ॉल्ट स्लॉट props.children
है और render
फ़ंक्शन तय करता है कि डिफ़ॉल्ट स्लॉट कहां रखा जाता है. उदाहरण के लिए:
const MyArticle = (props) => {
return <article>{props.children}</article>;
};
ध्यान रखें कि props.children
, रिऐक्ट कॉम्पोनेंट हैं, न कि एचटीएमएल एलिमेंट.
लिट में, बच्चों को रेंडर फ़ंक्शन में स्लॉट एलिमेंट का इस्तेमाल किया जाता है. ध्यान दें कि बच्चों को रिऐक्ट की तरह इनहेरिट नहीं किया जाता. लिट में, चिल्ड्रन स्लॉट से जुड़े HTMLElements होते हैं. इस अटैचमेंट को प्रक्षेपण कहा जाता है.
@customElement("my-article")
export class MyArticle extends LitElement {
render() {
return html`
<article>
<slot></slot>
</article>
`;
}
}
एक से ज़्यादा स्लॉट
React में, कई स्लॉट जोड़ना ज़रूरी है, जो कि ज़्यादा प्रॉपर्टी को इनहेरिट करने जैसा ही होता है.
const MyArticle = (props) => {
return (
<article>
<header>
{props.headerChildren}
</header>
<section>
{props.sectionChildren}
</section>
</article>
);
};
इसी तरह, ज़्यादा <slot>
एलिमेंट जोड़ने से, Lit में ज़्यादा स्लॉट बन जाते हैं. name
एट्रिब्यूट के साथ एक से ज़्यादा स्लॉट तय किए गए हैं: <slot name="slot-name">
. इससे बच्चे यह तय कर सकते हैं कि उन्हें कौनसा स्लॉट असाइन किया जाएगा.
@customElement("my-article")
export class MyArticle extends LitElement {
render() {
return html`
<article>
<header>
<slot name="headerChildren"></slot>
</header>
<section>
<slot name="sectionChildren"></slot>
</section>
</article>
`;
}
}
डिफ़ॉल्ट स्लॉट सामग्री
जब उस स्लॉट में कोई नोड प्रोजेक्ट नहीं किया जाएगा, तब स्लॉट अपना सबट्री दिखाएंगे. जब नोड किसी स्लॉट के लिए प्रोजेक्ट किए जाते हैं, तो वह स्लॉट अपनी सबट्री नहीं दिखाएगा और इसके बजाय अनुमानित नोड दिखाएगा.
@customElement("my-element")
export class MyElement extends LitElement {
render() {
return html`
<section>
<div>
<slot name="slotWithDefault">
<p>
This message will not be rendered when children are attached to this slot!
<p>
</slot>
</div>
</section>
`;
}
}
बच्चों को स्लॉट असाइन करें
प्रतिक्रिया में, बच्चों को कॉम्पोनेंट की प्रॉपर्टी के ज़रिए स्लॉट असाइन किए जाते हैं. नीचे दिए गए उदाहरण में, प्रतिक्रिया देने वाले एलिमेंट को headerChildren
और sectionChildren
प्रॉपर्टी में पास किया गया है.
const MyNewsArticle = () => {
return (
<MyArticle
headerChildren={<h3>Extry, Extry! Read all about it!</h3>}
sectionChildren={<p>Children are props in React!</p>}
/>
);
};
'लिट' में, बच्चों को slot
एट्रिब्यूट का इस्तेमाल करके स्लॉट असाइन किए जाते हैं.
@customElement("my-news-article")
export class MyNewsArticle extends LitElement {
render() {
return html`
<my-article>
<h3 slot="headerChildren">
Extry, Extry! Read all about it!
</h3>
<p slot="sectionChildren">
Children are composed with slots in Lit!
</p>
</my-article>
`;
}
}
अगर कोई डिफ़ॉल्ट स्लॉट (जैसे कि <slot>
) न हो और ऐसा कोई स्लॉट न हो जिसमें कस्टम एलिमेंट के चाइल्ड के slot
एट्रिब्यूट (जैसे कि <div slot="foo">
) से मेल खाने वाला name
एट्रिब्यूट (उदाहरण के लिए, <slot name="foo">
) हो, तो वह नोड प्रोजेक्ट नहीं किया जाएगा और नहीं दिखेगा.
9. रेफ़रंस
कभी-कभी, डेवलपर को किसी HTMLElement के एपीआई को ऐक्सेस करना पड़ सकता है.
इस सेक्शन में, आपको Lit में एलिमेंट के रेफ़रंस पाने का तरीका पता चलेगा.
रिऐक्ट रेफ़रंस
रिऐक्ट कॉम्पोनेंट को फ़ंक्शन कॉल की ऐसी सीरीज़ में बदला जाता है जो शुरू करने पर एक वर्चुअल डीओएम बनाता है. इस वर्चुअल डीओएम को ReactDOM स्वीकार करता है और HTMLElements को रेंडर करता है.
React में, रेफ़रंस के तौर पर मेमोरी में स्पेस होता है, जिसमें जनरेट किया गया HTMLElement शामिल होता है.
const RefsExample = (props) => {
const inputRef = React.useRef(null);
const onButtonClick = React.useCallback(() => {
inputRef.current?.focus();
}, [inputRef]);
return (
<div>
<input type={"text"} ref={inputRef} />
<br />
<button onClick={onButtonClick}>
Click to focus on the input above!
</button>
</div>
);
};
ऊपर दिए गए उदाहरण में, प्रतिक्रिया देने वाला कॉम्पोनेंट ये काम करेगा:
- खाली टेक्स्ट इनपुट और टेक्स्ट वाला बटन रेंडर करें
- बटन पर क्लिक होने पर इनपुट पर फ़ोकस करें
पहली बार रेंडर होने के बाद React, ref
एट्रिब्यूट का इस्तेमाल करके inputRef.current
को जनरेट किए गए HTMLInputElement
पर सेट कर देगा.
लिटिल "रेफ़रंस" @query
के साथ
Lit, ब्राउज़र के आस-पास रहता है और मूल ब्राउज़र सुविधाओं के बारे में बहुत ही छोटा एब्सट्रैक्ट बनाता है.
Lit में refs
के बराबर React, @query
और @queryAll
डेकोरेटर से मिला एचटीएमएल एलिमेंट है.
@customElement("my-element")
export class MyElement extends LitElement {
@query('input') // Define the query
inputEl!: HTMLInputElement; // Declare the prop
// Declare the click event listener
onButtonClick() {
// Use the query to focus
this.inputEl.focus();
}
render() {
return html`
<input type="text">
<br />
<!-- Bind the click listener -->
<button @click=${this.onButtonClick}>
Click to focus on the input above!
</button>
`;
}
}
ऊपर दिए गए उदाहरण में, Lit कॉम्पोनेंट ये काम करता है:
@query
डेकोरेटर (HTMLInputElement
के लिए गैटर बनाना) का इस्तेमाल करके,MyElement
पर प्रॉपर्टी के बारे में बताता है.onButtonClick
नाम के एक क्लिक इवेंट कॉलबैक का एलान करता है और उसे अटैच करता है.- बटन क्लिक करने पर इनपुट फ़ोकस करता है
JavaScript में, @query
और @queryAll
डेकोरेटर querySelector
और querySelectorAll
की परफ़ॉर्मेंस देते हैं. यह @query('input') inputEl!: HTMLInputElement;
के बराबर की JavaScript है
get inputEl() {
return this.renderRoot.querySelector('input');
}
Lit कॉम्पोनेंट, render
तरीके के टेंप्लेट को my-element
के रूट से जोड़ने के बाद, @query
डेकोरेटर से inputEl
, रेंडर रूट में मौजूद पहला input
एलिमेंट दिखा पाएगा. अगर @query
को बताया गया एलिमेंट नहीं मिलता, तो यह null
वैल्यू दिखाएगा.
अगर रेंडर रूट में एक से ज़्यादा input
एलिमेंट थे, तो @queryAll
नोड की सूची दिखाएगा.
10. मध्यस्थता स्थिति
इस सेक्शन में, आपको Lit में कॉम्पोनेंट के बीच मीडिएट करने के तरीके के बारे में जानकारी मिलेगी.
फिर से इस्तेमाल किए जा सकने वाले कॉम्पोनेंट
टॉप डाउन डेटा फ़्लो के साथ, काम करने वाले रेंडरिंग पाइपलाइन की तरह प्रतिक्रिया देता है. माता-पिता चीज़ों का इस्तेमाल करके, अपने बच्चों को स्थिति के बारे में बताते हैं. प्रॉप में मिलने वाले कॉलबैक के ज़रिए बच्चे, माता-पिता से बातचीत करते हैं.
const CounterButton = (props) => {
const label = props.step < 0
? `- ${-1 * props.step}`
: `+ ${props.step}`;
return (
<button
onClick={() =>
props.addToCounter(props.step)}>{label}</button>
);
};
ऊपर दिए गए उदाहरण में, प्रतिक्रिया देने वाला एक कॉम्पोनेंट ये काम करता है:
props.step
वैल्यू के आधार पर लेबल बनाता है.- इसके लेबल के रूप में +step या -step का बटन रेंडर करता है
- क्लिक पर तर्क के रूप में
props.step
को कॉल करकेprops.addToCounter
को कॉल करके पैरंट कॉम्पोनेंट को अपडेट करता है
Lit में कॉलबैक पास किए जा सकते हैं, लेकिन कंवेंशनल पैटर्न अलग होते हैं. ऊपर दिए गए उदाहरण में, रिऐक्ट कॉम्पोनेंट को नीचे दिए गए उदाहरण में लिट कॉम्पोनेंट के तौर पर लिखा जा सकता है:
@customElement('counter-button')
export class CounterButton extends LitElement {
@property({type: Number}) step: number = 0;
onClick() {
const event = new CustomEvent('update-counter', {
bubbles: true,
detail: {
step: this.step,
}
});
this.dispatchEvent(event);
}
render() {
const label = this.step < 0
? `- ${-1 * this.step}` // "- 1"
: `+ ${this.step}`; // "+ 1"
return html`
<button @click=${this.onClick}>${label}</button>
`;
}
}
ऊपर दिए गए उदाहरण में, लिट कॉम्पोनेंट ये काम करेगा:
- रीऐक्टिव प्रॉपर्टी
step
बनाएं - क्लिक करने पर, एलिमेंट की
step
वैल्यू को शामिल करने वालेupdate-counter
नाम के कस्टम इवेंट को डिस्पैच करें
ब्राउज़र इवेंट का बबल, चाइल्ड एलिमेंट से लेकर पैरंट एलिमेंट तक का होता है. इवेंट की मदद से बच्चे, इंटरैक्शन से जुड़े इवेंट और स्थिति में हुए बदलावों को ब्रॉडकास्ट कर सकते हैं. दरअसल, रिऐक्ट की स्थिति बिलकुल उलट होती है. इसलिए, यह आम बात नहीं है कि रिऐक्ट कॉम्पोनेंट्स को डिस्पैच होते हुए देखा जा सकता है और इवेंट को लिट कॉम्पोनेंट की तरह ही सुना जा सकता है.
स्टेटफ़ुल कॉम्पोनेंट
React में, स्टेट मैनेज करने के लिए हुक का इस्तेमाल करना आम बात है. CounterButton
कॉम्पोनेंट का फिर से इस्तेमाल करके, MyCounter
कॉम्पोनेंट बनाया जा सकता है. ध्यान दें कि CounterButton
के दोनों इंस्टेंस में addToCounter
कैसे पास किया जाता है.
const MyCounter = (props) => {
const [counterSum, setCounterSum] = React.useState(0);
const addToCounter = useCallback(
(step) => {
setCounterSum(counterSum + step);
},
[counterSum, setCounterSum]
);
return (
<div>
<h3>Σ: {counterSum}</h3>
<CounterButton
step={-1}
addToCounter={addToCounter} />
<CounterButton
step={1}
addToCounter={addToCounter} />
</div>
);
};
ऊपर दिया गया उदाहरण ये काम करता है:
count
स्थिति सेट करता है.- ऐसा कॉलबैक बनाता है जो
count
स्टेट में नंबर जोड़ता है. CounterButton
, हर क्लिक परcount
कोstep
से अपडेट करने के लिए,addToCounter
का इस्तेमाल करता है.
MyCounter
को लागू करने की ऐसी ही एक प्रोसेस, Lit में लागू की जा सकती है. ध्यान दें कि counter-button
को addToCounter
कैसे पास नहीं किया जाता. इसके बजाय, कॉलबैक, पैरंट एलिमेंट पर @update-counter
इवेंट के लिए, इवेंट लिसनर के तौर पर बाउंड होता है.
@customElement("my-counter")
export class MyCounter extends LitElement {
@property({type: Number}) count = 0;
addToCounter(e: CustomEvent<{step: number}>) {
// Get step from detail of event or via @query
this.count += e.detail.step;
}
render() {
return html`
<div @update-counter="${this.addToCounter}">
<h3>Σ ${this.count}</h3>
<counter-button step="-1"></counter-button>
<counter-button step="1"></counter-button>
</div>
`;
}
}
ऊपर दिया गया उदाहरण ये काम करता है:
count
नाम की एक रिऐक्टिव प्रॉपर्टी बनाता है, जो वैल्यू बदलने पर कॉम्पोनेंट को अपडेट कर देती है- यह
addToCounter
कॉलबैक को@update-counter
इवेंट लिसनर से बाइंड करता है update-counter
इवेंट केdetail.step
में मिली वैल्यू को जोड़कर,count
को अपडेट करता है- यह
step
एट्रिब्यूट के ज़रिए,counter-button
कीstep
वैल्यू सेट करता है
माता-पिता के बदलावों को बच्चों में ब्रॉडकास्ट करने के लिए, Lit में रिऐक्टिव प्रॉपर्टी इस्तेमाल करना ज़्यादा आसान है. इसी तरह, ब्राउज़र के इवेंट सिस्टम का इस्तेमाल करके, सबसे नीचे से जानकारी को बबल के लिए इस्तेमाल करना भी एक अच्छा तरीका है.
यह तरीका, सबसे सही तरीकों का पालन करता है. साथ ही, यह वेब कॉम्पोनेंट के लिए क्रॉस-प्लैटफ़ॉर्म सहायता उपलब्ध कराने के Lit के लक्ष्य का पालन करता है.
11. शैलीकृत करना
इस सेक्शन में, आपको Lit में स्टाइलिंग के बारे में जानकारी मिलेगी.
शैलीकृत करना
Lit में एलिमेंट को स्टाइल करने के कई तरीके हैं. साथ ही, इसमें पहले से मौजूद सुविधा भी उपलब्ध है.
इनलाइन स्टाइल
Lit, इनलाइन स्टाइल के साथ-साथ उन्हें बाइंड करने की सुविधा देता है.
import {LitElement, html, css} from 'lit';
import {customElement} from 'lit/decorators.js';
@customElement('my-element')
class MyElement extends LitElement {
render() {
return html`
<div>
<h1 style="color:orange;">This text is orange</h1>
<h1 style="color:rebeccapurple;">This text is rebeccapurple</h1>
</div>
`;
}
}
ऊपर दिए गए उदाहरण में इनलाइन स्टाइल के साथ दो हेडिंग हैं.
अब border-color.js
से बॉर्डर को इंपोर्ट करें और नारंगी टेक्स्ट से बाइंड करें:
...
import borderColor from './border-color.js';
...
html`
...
<h1 style="color:orange;${borderColor}">This text is orange</h1>
...`
हर बार स्टाइल स्ट्रिंग को कैलकुलेट करने से परेशानी हो सकती है. इसलिए, Lit इस काम में मदद करने के लिए निर्देश देता है.
styleMap
styleMap
डायरेक्टिव, इनलाइन स्टाइल सेट करने के लिए JavaScript का इस्तेमाल करना आसान बनाता है. उदाहरण के लिए:
import {LitElement, html, css} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {styleMap} from 'lit/directives/style-map.js';
@customElement('my-element')
class MyElement extends LitElement {
@property({type: String})
color = '#000'
render() {
// Define the styleMap
const headerStyle = styleMap({
'border-color': this.color,
});
return html`
<div>
<h1
style="border-style:solid;
<!-- Use the styleMap -->
border-width:2px;${headerStyle}">
This div has a border color of ${this.color}
</h1>
<input
type="color"
@input=${e => (this.color = e.target.value)}
value="#000">
</div>
`;
}
}
ऊपर दिया गया उदाहरण ये काम करता है:
- बॉर्डर और कलर पिकर के साथ
h1
दिखाता है - यह
border-color
को कलर पिकर से वैल्यू में बदलता है
इसके अलावा, एक ऐसी सुविधा styleMap
है जिसका इस्तेमाल h1
की स्टाइल सेट करने के लिए किया जाता है. styleMap
, React के style
एट्रिब्यूट बाइंडिंग सिंटैक्स से मिलते-जुलते सिंटैक्स को फ़ॉलो करता है.
CSSResult
कॉम्पोनेंट को स्टाइल करने का सुझाया गया तरीका, टैग किए गए css
टेंप्लेट का लिटरल इस्तेमाल करना है.
import {LitElement, html, css} from 'lit';
import {customElement} from 'lit/decorators.js';
const ORANGE = css`orange`;
@customElement('my-element')
class MyElement extends LitElement {
static styles = [
css`
#orange {
color: ${ORANGE};
}
#purple {
color: rebeccapurple;
}
`
];
render() {
return html`
<div>
<h1 id="orange">This text is orange</h1>
<h1 id="purple">This text is rebeccapurple</h1>
</div>
`;
}
}
ऊपर दिया गया उदाहरण ये काम करता है:
- बाइंडिंग के साथ सीएसएस टैग किए गए टेंप्लेट का लिटरल एलान करता है
- आईडी के साथ दो
h1
के रंग सेट करता है
css
टेंप्लेट टैग को इस्तेमाल करने के फ़ायदे:
- हर क्लास के हिसाब से एक बार पार्स किया गया और हर इंस्टेंस के हिसाब से
- मॉड्यूल की फिर से इस्तेमाल करने की क्षमता को ध्यान में रखते हुए लागू किया गया है
- स्टाइल को आसानी से उनकी फ़ाइलों में अलग कर सकता है
- सीएसएस कस्टम प्रॉपर्टी की पॉलीफ़िल के साथ काम करता है
इसके अलावा, index.html
में मौजूद <style>
टैग पर ध्यान दें:
<!-- index.html -->
<style>
h1 {
color: red !important;
}
</style>
Lite, आपके कॉम्पोनेंट का स्कोप करेगा' स्टाइल शामिल हैं. इसका मतलब है कि स्टाइल, अंदर और बाहर लीक नहीं होंगे. सभी कॉम्पोनेंट के बीच स्टाइल पास करने के लिए, Lit टीम सीएसएस की कस्टम प्रॉपर्टी का इस्तेमाल करने का सुझाव देती है. इससे, वे लिटिल स्टाइल स्कोपिंग में शामिल हो सकते हैं.
स्टाइल टैग
आपके टेंप्लेट में <style>
टैग को भी इनलाइन किया जा सकता है. ब्राउज़र, इन स्टाइल टैग की डुप्लीकेट कॉपी को हटा देगा. हालांकि, इन्हें आपके टेंप्लेट में डालने पर, इन्हें css
टैग किए गए टेंप्लेट की तरह, हर क्लास की तरह कॉम्पोनेंट इंस्टेंस के हिसाब से पार्स किया जाएगा. इसके अलावा, ब्राउज़र में CSSResult
की डुप्लीकेट कॉपी हटाने की तकनीक ज़्यादा तेज़ी से काम करती है.
लिंक टैग
अपने टेंप्लेट में <link rel="stylesheet">
का इस्तेमाल करने से, स्टाइल भी बनाए जा सकते हैं. हालांकि, हमारा सुझाव है कि ऐसा न करें, क्योंकि इससे बिना स्टाइल वाले कॉन्टेंट (एफ़ओयूसी) का शुरुआती फ़्लैश शुरू हो सकता है.
12. बेहतर विषय (ज़रूरी नहीं)
JSX और टेंप्लेट बनाया जा रहा है
लाइट ऐंड वर्चुअल डीओएम
Lit-html में ऐसा कंवेंशनल वर्चुअल DOM शामिल नहीं है जो हर नोड में अंतर करता है. इसके बजाय, यह ES2015 के टैग किए गए टेंप्लेट की लिटरल स्पेसिफ़िकेशन में दी गई परफ़ॉर्मेंस की सुविधाओं का इस्तेमाल करता है. टैग किए गए टेंप्लेट की लिटरल स्ट्रिंग, टेंप्लेट की लिटरल स्ट्रिंग हैं. इनमें टैग फ़ंक्शन जुड़े होते हैं.
यहां लिटरल वैल्यू वाले टेंप्लेट का एक उदाहरण दिया गया है:
const str = 'string';
console.log(`This is a template literal ${str}`);
यहां टैग किए गए टेंप्लेट का एक उदाहरण दिया गया है:
const tag = (strings, ...values) => ({strings, values});
const f = (x) => tag`hello ${x} how are you`;
console.log(f('world')); // {strings: ["hello ", " how are you"], values: ["world"]}
console.log(f('world').strings === f(1 + 2).strings); // true
ऊपर दिए गए उदाहरण में, टैग tag
फ़ंक्शन है और f
फ़ंक्शन, टैग किए गए टेंप्लेट की लिटरल वैल्यू दिखाता है.
लिटरेचर में परफ़ॉर्मेंस की कई खासियतें इस बात से आती हैं कि टैग फ़ंक्शन में पास की गई स्ट्रिंग अरे का पॉइंटर एक ही होता है (जैसा कि दूसरे console.log
में दिखाया गया है). ब्राउज़र, टैग फ़ंक्शन को शुरू करने के लिए हर टैग फ़ंक्शन पर नई strings
अरे को फिर से नहीं बनाता. ऐसा इसलिए, क्योंकि वह उसी टेंप्लेट लिटरल (जैसे कि AST में उसी जगह पर) का इस्तेमाल कर रहा है. इसलिए, Lit की बाइंडिंग, पार्स करने, और टेंप्लेट की कैश मेमोरी में बदलाव करने की सुविधा, इन सुविधाओं का फ़ायदा ले सकती है. इसके लिए, रनटाइम के दौरान ज़्यादा खर्च नहीं करना पड़ता.
टैग किए गए टेंप्लेट के लिटरल बिल्ट-इन ब्राउज़र व्यवहार से Lit को परफ़ॉर्मेंस में काफ़ी फ़ायदा मिलता है. ज़्यादातर परंपरागत वर्चुअल डीओएम अपना ज़्यादातर काम JavaScript में करते हैं. हालांकि, टैग किए गए टेंप्लेट की लिटरल वैल्यू, ब्राउज़र के C++ में आने वाले ज़्यादातर अंतर को पूरा करती है.
अगर आपको React या Preact के साथ, एचटीएमएल टैग किए गए टेंप्लेट के लिटरल इस्तेमाल करना है, तो Lit टीम htm
लाइब्रेरी का सुझाव देती है.
हालांकि, जैसा कि Google Codelabs और कई ऑनलाइन कोड एडिटर के मामले में होता है, टैग किए गए टेंप्लेट का लिटरल सिंटैक्स हाइलाइट करने का तरीका आम नहीं है. कुछ आईडीई और टेक्स्ट एडिटर, डिफ़ॉल्ट रूप से इनके साथ काम करते हैं. जैसे, ऐटम और GitHub का कोडब्लॉक हाइलाइटर. Lit टीम भी समुदाय के साथ मिलकर काम करती है, ताकि lit-plugin
जैसे प्रोजेक्ट मैनेज किए जा सकें. यह एक वीएस कोड प्लगिन है, जो आपके Lit प्रोजेक्ट में सिंटैक्स हाइलाइट करने, टाइप चेक करने, और इंटेलिजेंस जोड़ने में मदद करता है.
लाइट ऐंड JSX + प्रतिक्रिया DOM
JSX ब्राउज़र में नहीं चलता है और इसके बजाय, वह JSX को JavaScript फ़ंक्शन कॉल (आम तौर पर बेबेल के ज़रिए) में बदलने के लिए प्रीप्रोसेसर का इस्तेमाल करता है.
उदाहरण के लिए, बेबल इसे बदल देगा:
const element = <div className="title">Hello World!</div>;
ReactDOM.render(element, mountNode);
इसमें शामिल करें:
const element = React.createElement('div', {className: 'title'}, 'Hello World!');
ReactDOM.render(element, mountNode);
इसके बाद, React DOM आउटपुट देता है और उसे असल डीओएम में बदल देता है. इसमें प्रॉपर्टी, एट्रिब्यूट, इवेंट लिसनर वगैरह शामिल हैं.
Lit-html, टैग किए गए टेंप्लेट की लिटरल वैल्यू का इस्तेमाल करता है जो ब्राउज़र में बिना ट्रांसपिलेशन या प्रीप्रोसेसर के चल सकता है. इसका मतलब है कि Lit का इस्तेमाल शुरू करने के लिए, आपको सिर्फ़ एक एचटीएमएल फ़ाइल, एक ES मॉड्यूल स्क्रिप्ट, और एक सर्वर की ज़रूरत होगी. यह पूरी तरह से ब्राउज़र द्वारा चलाई जा सकने वाली स्क्रिप्ट है:
<!DOCTYPE html>
<html>
<head>
<script type="module">
import {html, render} from 'https://cdn.skypack.dev/lit';
render(
html`<div>Hello World!</div>`,
document.querySelector('.root')
)
</script>
</head>
<body>
<div class="root"></div>
</body>
</html>
साथ ही, Lit का टेंप्लेटिंग सिस्टम, lit-html, जो पारंपरिक वर्चुअल DOM का इस्तेमाल नहीं करता, बल्कि सीधे DOM API का इस्तेमाल करता है. इसलिए, Lit 2 का साइज़ React (2.8kb) + React (2.8kb) + प्रतिक्रिया-डॉम (39.4kb) की तुलना में gzip किया गया और छोटा किया गया है.
इवेंट
React, सिंथेटिक इवेंट सिस्टम का इस्तेमाल करता है. इसका मतलब है कि प्रतिक्रिया-डॉम को हर वह इवेंट तय करना चाहिए जिसका इस्तेमाल हर कॉम्पोनेंट पर किया जाएगा. साथ ही, हर तरह के नोड के लिए CamlCase इवेंट लिसनर उपलब्ध कराता है. इस वजह से, JSX में किसी कस्टम इवेंट के लिए, इवेंट लिसनर तय करने का कोई तरीका नहीं है. साथ ही, डेवलपर को ref
का इस्तेमाल करना होगा. इसके बाद, लिसनर को लागू करना होगा. इससे, उन लाइब्रेरी को इंटिग्रेट करने पर डेवलपर का अनुभव बेहतर होता है जो React का इस्तेमाल न करती हों. इससे, आपको React के हिसाब से रैपर लिखना पड़ता है.
Lit-html सीधे DOM को ऐक्सेस करता है और नेटिव इवेंट का इस्तेमाल करता है. इसलिए, इवेंट लिसनर जोड़ना @event-name=${eventNameListener}
जितना आसान है. इसका मतलब है कि इवेंट लिसनर जोड़ने के साथ-साथ इवेंट ट्रिगर करने के लिए, रनटाइम को कम पार्स किया जाता है.
कॉम्पोनेंट और प्रॉप्स
रिऐक्ट कॉम्पोनेंट और कस्टम एलिमेंट
हुड के तहत, LitElement ने अपने कॉम्पोनेंट को पैकेज करने के लिए कस्टम एलिमेंट का इस्तेमाल किया है. कस्टम एलिमेंट, कॉम्पोनेंटाइज़ेशन के मामले में, React कॉम्पोनेंट के बीच कुछ अंतर कर देते हैं. राज्य और लाइफ़साइकल सेक्शन में, स्थिति और लाइफ़साइकल के बारे में ज़्यादा जानकारी दी गई है.
कस्टम एलिमेंट के कॉम्पोनेंट सिस्टम के कुछ फ़ायदे:
- यह ब्राउज़र पर काम करता है और इसके लिए किसी टूल की ज़रूरत नहीं होती
innerHTML
औरdocument.createElement
सेquerySelector
तक, हर ब्राउज़र एपीआई में फ़िट होता है- आम तौर पर, इसे सभी फ़्रेमवर्क में इस्तेमाल किया जा सकता है
customElements.define
और "हाइड्रेट" के साथ लेज़ी तरीके से रजिस्टर किया जा सकता है डीओएम
कस्टम एलिमेंट के कुछ नुकसान, रिऐक्ट कॉम्पोनेंट की तुलना में होते हैं:
- क्लास परिभाषित किए बिना कस्टम एलिमेंट नहीं बनाया जा सकता (इसलिए, JSX जैसा कोई फ़ंक्शनल कॉम्पोनेंट नहीं है)
- क्लोज़िंग टैग
- होना चाहिए
- ध्यान दें: इसके बावजूद, डेवलपर की सुविधा वाले ब्राउज़र वेंडर को अपने-आप बंद होने वाले टैग की खास बातों पर पछतावा होता है. इसलिए, नए स्पेसिफ़िकेशन में खुद बंद होने वाले टैग शामिल नहीं किए जाते हैं
- डीओएम ट्री में एक और नोड शामिल करता है, जिससे लेआउट से जुड़ी समस्याएं हो सकती हैं
- JavaScript के ज़रिए रजिस्टर होना चाहिए
Lit ने पसंद के मुताबिक बनाए गए एलिमेंट सिस्टम के बजाय कस्टम एलिमेंट का इस्तेमाल किया है, क्योंकि ब्राउज़र में कस्टम एलिमेंट पहले से मौजूद होते हैं. Lit की टीम का मानना है कि क्रॉस-फ़्रेमवर्क से मिलने वाले फ़ायदों के मुकाबले, कॉम्पोनेंट ऐब्स्ट्रैक्ट लेयर से मिलने वाले फ़ायदे ज़्यादा होते हैं. बल्कि, लिट-एसआर स्पेस में Lit टीम की कोशिशों ने JavaScript रजिस्ट्रेशन से जुड़ी मुख्य समस्याओं को दूर कर दिया है. इसके अलावा, GitHub जैसी कुछ कंपनियां, कस्टम एलिमेंट के लिए लेज़ी रजिस्ट्रेशन की सुविधा का इस्तेमाल करती हैं. इससे पेजों को बेहतर बनाने के लिए, अलग-अलग विकल्प का इस्तेमाल किया जाता है.
कस्टम एलिमेंट को डेटा भेजना
कस्टम एलिमेंट के साथ एक आम गलतफ़हमी यह है कि डेटा को सिर्फ़ स्ट्रिंग के तौर पर पास किया जा सकता है. यह गलतफ़हमी इस बात से आ सकती है कि एलिमेंट के एट्रिब्यूट को सिर्फ़ स्ट्रिंग के तौर पर लिखा जा सकता है. हालांकि, यह बात सही है कि Lit, स्ट्रिंग एट्रिब्यूट को तय किए गए टाइप में कास्ट करेगा, लेकिन कस्टम एलिमेंट भी मुश्किल डेटा को प्रॉपर्टी के तौर पर स्वीकार कर सकते हैं.
उदाहरण के लिए - नीचे दी गई LitElement की परिभाषा:
// data-test.ts
import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';
@customElement('data-test')
class DataTest extends LitElement {
@property({type: Number})
num = 0;
@property({attribute: false})
data = {a: 0, b: null, c: [html`<div>hello</div>`, html`<div>world</div>`]}
render() {
return html`
<div>num + 1 = ${this.num + 1}</div>
<div>data.a = ${this.data.a}</div>
<div>data.b = ${this.data.b}</div>
<div>data.c = ${this.data.c}</div>`;
}
}
ऐसी प्रिमिटिव रिऐक्टिव प्रॉपर्टी num
तय की गई है जो किसी एट्रिब्यूट की स्ट्रिंग वैल्यू को number
में बदल देती है. इसके बाद, attribute:false
का इस्तेमाल करके कॉम्प्लेक्स डेटा स्ट्रक्चर तैयार किया जाता है, जो Lit के एट्रिब्यूट को मैनेज करने की सुविधा बंद कर देता है.
इस कस्टम एलिमेंट में डेटा भेजने का तरीका यहां बताया गया है:
<head>
<script type="module">
import './data-test.js'; // loads element definition
import {html} from './data-test.js';
const el = document.querySelector('data-test');
el.data = {
a: 5,
b: null,
c: [html`<div>foo</div>`,html`<div>bar</div>`]
};
</script>
</head>
<body>
<data-test num="5"></data-test>
</body>
राज्य & लाइफ़साइकल
अन्य रीऐक्ट लाइफ़साइकल कॉलबैक
static getDerivedStateFromProps
Lit में प्रॉप्स और स्टेट, दोनों एक ही क्लास प्रॉपर्टी नहीं हैं
shouldComponentUpdate
- लिटरल वैल्यू
shouldUpdate
के बराबर है - प्रतिक्रिया के उलट पहली इमेज पर कॉल किया गया
- रिऐक्ट के
shouldComponentUpdate
के फ़ंक्शन में मिलता-जुलता
getSnapshotBeforeUpdate
लिट में, getSnapshotBeforeUpdate
, update
और willUpdate
, दोनों से मिलती-जुलती है
willUpdate
update
से पहले कॉल कियाgetSnapshotBeforeUpdate
के उलट,render
से पहलेwillUpdate
को कॉल किया जाता हैwillUpdate
की रिऐक्टिव प्रॉपर्टी में बदलाव करने पर, अपडेट साइकल फिर से ट्रिगर नहीं होता- यह ऐसी प्रॉपर्टी वैल्यू को कैलकुलेट करने का बेहतरीन तरीका है जो अन्य प्रॉपर्टी पर निर्भर करती हैं. साथ ही, इनका इस्तेमाल अपडेट करने की बाकी प्रोसेस में किया जाता है
- यह तरीका एसएसआर में सर्वर पर कॉल किया जाता है. इसलिए, यहां डीओएम को ऐक्सेस करने का सुझाव नहीं दिया जाता है
update
willUpdate
के बाद कॉल कियाgetSnapshotBeforeUpdate
के उलट,render
से पहलेupdate
को कॉल किया जाता हैupdate
की रिऐक्टिव प्रॉपर्टी में किए जाने वाले बदलावों से, अपडेट साइकल फिर से ट्रिगर नहीं होता. ऐसा तब होता है, जबsuper.update
को कॉल करने से पहले ऐसा किया जाता है- रेंडर किए गए आउटपुट को डीओएम के लिए पूरा करने से पहले, कॉम्पोनेंट के आस-पास के डीओएम से जानकारी कैप्चर करने के लिए यह अच्छी जगह है
- एसएसआर में सर्वर पर इस तरीके को कॉल नहीं किया जाता है
अन्य Lit Lifecycle कॉलबैक
ऐसे कई लाइफ़साइकल कॉलबैक हैं जिनके बारे में पिछले सेक्शन में नहीं बताया गया था, क्योंकि React में उनके लिए कोई ऐनालॉग नहीं है. ये वजह हैं:
attributeChangedCallback
यह तब शुरू होता है, जब किसी एलिमेंट के observedAttributes
में बदलाव होता है. observedAttributes
और attributeChangedCallback
, दोनों ही कस्टम एलिमेंट की खास जानकारी का हिस्सा हैं. इन्हें Lit ने हुड के तहत लागू किया है, ताकि Lit एलिमेंट के लिए एट्रिब्यूट एपीआई उपलब्ध कराया जा सके.
adoptedCallback
यह तब इस्तेमाल होता है, जब कॉम्पोनेंट को किसी नए दस्तावेज़ में ले जाया जाता है, जैसे कि HTMLTemplateElement
के documentFragment
से मुख्य document
तक. यह कॉलबैक, कस्टम एलिमेंट से जुड़ी खास जानकारी का भी हिस्सा है. इसका इस्तेमाल सिर्फ़ तब करना चाहिए, जब कॉम्पोनेंट दस्तावेज़ों को बदलता है.
लाइफ़साइकल के अन्य तरीके और प्रॉपर्टी
ये तरीके और प्रॉपर्टी, क्लास के ऐसे सदस्य हैं जिन्हें कॉल किया जा सकता है, बदला जा सकता है या लाइफ़साइकल प्रोसेस में बदलाव करने में मदद मिलने का इंतज़ार किया जा सकता है.
updateComplete
यह एक Promise
है, जो एलिमेंट के अपडेट होने के बाद रिज़ॉल्व हो जाता है. अपडेट और रेंडर होने की लाइफ़साइकल एसिंक्रोनस होते हैं. एक उदाहरण:
async nextButtonClicked() {
this.step++;
// Wait for the next "step" state to render
await this.updateComplete;
this.dispatchEvent(new Event('step-rendered'));
}
getUpdateComplete
यह एक तरीका है, जिसे updateComplete
के ठीक होने के बाद, पसंद के मुताबिक बनाने के लिए ओवरराइड किया जाना चाहिए. ऐसा तब होता है, जब कोई कॉम्पोनेंट किसी चाइल्ड कॉम्पोनेंट को रेंडर करता है और उसका रेंडर साइकल सिंक होना चाहिए. उदाहरण,
class MyElement extends LitElement {
...
async getUpdateComplete() {
await super.getUpdateComplete();
await this.myChild.updateComplete;
}
}
performUpdate
यह तरीका, अपडेट लाइफ़साइकल कॉलबैक को कॉल करता है. आम तौर पर, इसकी ज़रूरत नहीं होती. हालांकि, ऐसा कुछ मामलों में होता है जहां अपडेट सिंक्रोनस या कस्टम शेड्यूलिंग के लिए किया जाना चाहिए.
hasUpdated
अगर कॉम्पोनेंट कम से कम एक बार अपडेट हुआ है, तो यह प्रॉपर्टी true
होगी.
isConnected
अगर एलिमेंट मौजूदा समय में दस्तावेज़ के मुख्य ट्री से जुड़ा है, तो कस्टम एलिमेंट स्पेसिफ़िकेशन का हिस्सा है, तो यह प्रॉपर्टी true
होगी.
लिट अपडेट लाइफ़साइकल विज़ुअलाइज़ेशन
अपडेट की लाइफ़साइकल के तीन हिस्से होते हैं:
- प्री-अपडेट
- अपडेट करें
- अपडेट के बाद
प्री-अपडेट
आपको requestUpdate
के बाद, शेड्यूल किए गए अपडेट का इंतज़ार है.
अपडेट करें
अपडेट के बाद
Hooks
हुक क्यों
ज़रूरी होने पर ही, फ़ंक्शन में इस्तेमाल होने वाले कॉम्पोनेंट के इस्तेमाल के लिए हुक का इस्तेमाल किया गया. कई आसान मामलों में, हुक वाले फ़ंक्शन के कॉम्पोनेंट अपने क्लास कॉम्पोनेंट वाले काउंटरपार्ट की तुलना में ज़्यादा आसान और पढ़ने लायक होते हैं. हालांकि, एसिंक्रोनस स्टेट अपडेट शुरू करते समय और हुक या इफ़ेक्ट के बीच डेटा पास करते समय, हुक पैटर्न काफ़ी नहीं होते. हालांकि, रिऐक्टिव कंट्रोलर जैसे क्लास-आधारित समाधान ज़्यादा कारगर साबित होते हैं.
एपीआई अनुरोध हुक और कंट्रोलर
एक हुक लिखना आम बात है, जो एपीआई से डेटा का अनुरोध करता है. उदाहरण के लिए, रिऐक्ट फ़ंक्शन का यह कॉम्पोनेंट लें, जो ये काम करता है:
index.tsx
- टेक्स्ट रेंडर करता है
useAPI
के प्रतिसाद- को रेंडर करता है
- यूज़र आईडी + उपयोगकर्ता नाम
- त्रुटि संदेश
- उपयोगकर्ता 11 तक पहुंचने पर 404 (डिज़ाइन के मुताबिक)
- एपीआई फ़ेच करने की प्रोसेस रद्द होने पर, गड़बड़ी को रद्द करें
- लोडिंग संदेश
- यह एक कार्रवाई बटन रेंडर करता है
- अगला उपयोगकर्ता: जो अगले उपयोगकर्ता के लिए एपीआई को फ़ेच करता है
- रद्द करें: इससे एपीआई को फ़ेच करने की प्रोसेस रद्द होती है और गड़बड़ी दिखती है
useApi.tsx
- यह नीति,
useApi
कस्टम हुक के बारे में बताती है - किसी एपीआई से उपयोगकर्ता ऑब्जेक्ट को सिंक नहीं किया जाएगा
- उत्सर्जन:
- उपयोगकर्ता नाम
- फ़ेच करने की प्रोसेस लोड हो रही है या नहीं
- गड़बड़ी का कोई मैसेज
- फ़ेच करने की प्रोसेस रद्द करने के लिए कॉलबैक
- अलग किए जाने पर, फ़ेच करने की प्रोसेस जारी है
- यह नीति,
यहां लिट + रिऐक्टिव कंट्रोलर को लागू करने का तरीका बताया गया है.
सीखने वाली अहम बातें:
- रिऐक्टिव कंट्रोलर आम तौर पर कस्टम हुक की तरह होते हैं
- कॉलबैक और इफ़ेक्ट के बीच रेंडर न किया जा सकने वाला डेटा पास करना
- React,
useRef
का इस्तेमाल करकेuseEffect
सेuseCallback
के बीच डेटा पास करता है - Lit एक प्राइवेट क्लास प्रॉपर्टी का इस्तेमाल करता है
- प्रतिक्रिया का मतलब है, किसी प्राइवेट क्लास प्रॉपर्टी की तरह व्यवहार करना
- React,
इसके अलावा, अगर आपको हुक के साथ React फ़ंक्शन कॉम्पोनेंट सिंटैक्स पसंद है, लेकिन Lit में बिना बदलाव वाला माहौल है, तो Lit टीम Haunted लाइब्रेरी इस्तेमाल करने का सुझाव देती है.
बच्चे
डिफ़ॉल्ट स्लॉट
जब एचटीएमएल एलिमेंट को slot
एट्रिब्यूट नहीं दिया जाता है, तो उन्हें बिना नाम वाले डिफ़ॉल्ट स्लॉट में असाइन कर दिया जाता है. नीचे दिए गए उदाहरण में, MyApp
एक पैराग्राफ़ को नाम वाले किसी स्लॉट में शामिल करेगा. दूसरा पैराग्राफ़ डिफ़ॉल्ट रूप से बिना नाम वाला स्लॉट होगा".
@customElement("my-element")
export class MyElement extends LitElement {
render() {
return html`
<section>
<div>
<slot></slot>
</div>
<div>
<slot name="custom-slot"></slot>
</div>
</section>
`;
}
}
@customElement("my-app")
export class MyApp extends LitElement {
render() {
return html`
<my-element>
<p slot="custom-slot">
This paragraph will be placed in the custom-slot!
</p>
<p>
This paragraph will be placed in the unnamed default slot!
</p>
</my-element>
`;
}
}
स्लॉट के अपडेट
स्लॉट डिसेंडेंट का स्ट्रक्चर बदलने पर, slotchange
इवेंट ट्रिगर होता है. लिटिल कॉम्पोनेंट, इवेंट सुनने वाले व्यक्ति को slotchange
इवेंट से बाइंड कर सकता है. नीचे दिए गए उदाहरण में, shadowRoot
में मिलने वाले पहले स्लॉट के लिए, slotchange
पर कंसोल में assignedNodes को लॉग किया जाएगा.
@customElement("my-element")
export class MyElement extends LitElement {
onSlotChange(e: Event) {
const slot = this.shadowRoot.querySelector('slot');
console.log(slot.assignedNodes({flatten: true}));
}
render() {
return html`
<section>
<div>
<slot @slotchange="{this.onSlotChange}"></slot>
</div>
</section>
`;
}
}
रेफ़रंस
रेफ़रंस जनरेशन
Lit और React, दोनों अपने render
फ़ंक्शन को कॉल करने के बाद, HTMLElement का रेफ़रंस दिखाते हैं. हालांकि, इस बात की समीक्षा की जा सकती है कि React और Lit ने डीओएम को कैसे कंपोज़ किया है. बाद में, इसे Lit @query
डेकोरेटर या रिऐक्ट रेफ़रंस के ज़रिए दिखाया जाता है.
React एक फ़ंक्शनल पाइपलाइन है, जो HTMLElements के बजाय React कॉम्पोनेंट बनाता है. HTMLElement को रेंडर होने से पहले ही Ref का एलान किया जाता है, इसलिए मेमोरी में एक स्पेस तय होता है. यही वजह है कि आपको null
को रेफ़रंस के तौर पर शुरुआती वैल्यू के तौर पर दिखता है, क्योंकि असली डीओएम एलिमेंट यानी कि useRef(null)
अब तक नहीं बनाया गया या रेंडर नहीं हुआ है.
जब ReactDOM एक प्रतिक्रिया वाले कॉम्पोनेंट को एक HTMLElement में बदल देता है, तब वह Reactcomponent में ref
नाम का एट्रिब्यूट खोजता है. उपलब्ध होने पर, ReactDOM, HTMLElement के रेफ़रंस को ref.current
में शामिल करता है.
LitElement, हुड के तहत टेंप्लेट एलिमेंट बनाने के लिए, lit-html से html
टेंप्लेट टैग फ़ंक्शन का इस्तेमाल करता है. LitElement, रेंडर करने के बाद टेंप्लेट के कॉन्टेंट को कस्टम एलिमेंट के शैडो डीओएम में स्टैंप करता है. शैडो डीओएम, स्कोप वाला डीओएम ट्री है, जिसे शैडो रूट के ज़रिए एनकैप्सुलेट करता है. इसके बाद, @query
डेकोरेटर उस प्रॉपर्टी के लिए गैटर बनाता है जो स्कोप वाले रूट पर this.shadowRoot.querySelector
करता है.
एक से ज़्यादा एलिमेंट के लिए क्वेरी करें
नीचे दिए गए उदाहरण में, @queryAll
डेकोरेटर शैडो रूट में मौजूद दो पैराग्राफ़ को NodeList
के रूप में दिखाएगा.
@customElement("my-element")
export class MyElement extends LitElement {
@queryAll('p')
paragraphs!: NodeList;
render() {
return html`
<p>Hello, world!</p>
<p>How are you?</p>
`;
}
}
असल में, @queryAll
, paragraphs
के लिए एक गैटर बनाता है, जो this.shadowRoot.querySelectorAll()
के नतीजे दिखाता है. JavaScript में, किसी गैटर को इसी काम के लिए एलान किया जा सकता है:
get paragraphs() {
return this.renderRoot.querySelectorAll('p');
}
क्वेरी में बदलाव करने वाले एलिमेंट
@queryAsync
डेकोरेटर ऐसे नोड को हैंडल करने के लिए बेहतर विकल्प है जो किसी अन्य एलिमेंट प्रॉपर्टी की स्थिति के आधार पर बदल सकता है.
नीचे दिए गए उदाहरण में, @queryAsync
को पहले पैराग्राफ़ एलिमेंट मिलेगा. हालांकि, पैराग्राफ़ एलिमेंट सिर्फ़ तब रेंडर किया जाएगा, जब renderParagraph
बिना किसी क्रम के कोई विषम संख्या जनरेट करेगा. @queryAsync
डायरेक्टिव, ऐसा प्रॉमिस देगा जो पहला पैराग्राफ़ उपलब्ध होने पर रिज़ॉल्व हो जाएगा.
@customElement("my-dissappearing-paragraph")
export class MyDisapppearingParagraph extends LitElement {
@queryAsync('p')
paragraph!: Promise<HTMLElement>;
renderParagraph() {
const randomNumber = Math.floor(Math.random() * 10)
if (randomNumber % 2 === 0) {
return "";
}
return html`<p>This checkbox is checked!`
}
render() {
return html`
${this.renderParagraph()}
`;
}
}
मध्यस्थता स्थिति
React में, कॉलबैक का इस्तेमाल किया जाता है, क्योंकि स्थिति की प्रतिक्रिया React खुद करती है. प्रतिक्रिया देने के लिए एलिमेंट से मिलने वाली स्थिति पर भरोसा न करना सबसे अच्छा होता है. डीओएम सिर्फ़ रेंडरिंग प्रोसेस का असर होता है.
बाहरी स्थिति
Lit के साथ-साथ Redux, MobX या किसी भी अन्य स्टेट मैनेजमेंट लाइब्रेरी का इस्तेमाल किया जा सकता है.
लिटिल कॉम्पोनेंट, ब्राउज़र के स्कोप में बनाए जाते हैं. इसलिए, ऐसी लाइब्रेरी जो ब्राउज़र के दायरे में भी मौजूद है वह Lit में उपलब्ध है. लिटिल में मौजूदा स्टेट मैनेजमेंट सिस्टम का इस्तेमाल करने के लिए, कई शानदार लाइब्रेरी बनाई गई हैं.
यह रही वाडिन की यह सीरीज़, जिसमें Lit कॉम्पोनेंट में Redux का इस्तेमाल करने का तरीका बताया गया है.
Adobe के lit-mobx पर नज़र डालें और जानें कि बड़े पैमाने पर काम करने वाली साइट, Lit में MobX का फ़ायदा कैसे ले सकती है.
इसके अलावा, Apolo एलिमेंट को देखकर यह भी जानें कि डेवलपर अपने वेब कॉम्पोनेंट में ग्राफ़क्यूएल को कैसे शामिल कर रहे हैं.
Lit, ब्राउज़र की नेटिव सुविधाओं के साथ काम करता है. साथ ही, ब्राउज़र के दायरे में आने वाले ज़्यादातर स्टेट मैनेजमेंट समाधान, Lit कॉम्पोनेंट में इस्तेमाल किए जा सकते हैं.
शैलीकृत करना
शैडो डीओएम
किसी कस्टम एलिमेंट में स्टाइल और डीओएम को नेटिव तौर पर इनकैप्सुलेट करने के लिए, Lit Shadow DOM का इस्तेमाल करता है. शैडो रूट, मुख्य दस्तावेज़ ट्री से अलग एक शैडो ट्री जनरेट करते हैं. इसका मतलब है कि ज़्यादातर स्टाइल इस दस्तावेज़ के दायरे में आते हैं. कुछ स्टाइल लीक हो जाते हैं, जैसे कि रंग और फ़ॉन्ट से जुड़ी दूसरी स्टाइल.
शैडो डीओएम, सीएसएस की खास बातों में नए कॉन्सेप्ट और सिलेक्टर को भी शामिल करता है:
:host, :host(:hover), :host([hover]) {
/* Styles the element in which the shadow root is attached to */
}
slot[name="title"]::slotted(*), slot::slotted(:hover), slot::slotted([hover]) {
/*
* Styles the elements projected into a slot element. NOTE: the spec only allows
* styling the direcly slotted elements. Children of those elements are not stylable.
*/
}
स्टाइल शेयर करना
Lit, css
टेंप्लेट टैग के ज़रिए, CSSTemplateResults
के रूप में कॉम्पोनेंट के बीच स्टाइल शेयर करना आसान बनाता है. उदाहरण के लिए:
// typography.ts
export const body1 = css`
.body1 {
...
}
`;
// my-el.ts
import {body1} from './typography.ts';
@customElement('my-el')
class MyEl Extends {
static get styles = [
body1,
css`/* local styles come after so they will override bod1 */`
]
render() {
return html`<div class="body1">...</div>`
}
}
थीम बनाई जा रही है
शैडो रूट्स पारंपरिक थीमिंग के लिए एक चुनौती पेश करते हैं जो आम तौर पर टॉप-डाउन स्टाइल टैग अप्रोच होते हैं. शैडो डीओएम का इस्तेमाल करने वाले वेब कॉम्पोनेंट की मदद से थीम बनाने का एक आसान तरीका यह है कि सीएसएस कस्टम प्रॉपर्टी के ज़रिए स्टाइल एपीआई को सार्वजनिक किया जाए. उदाहरण के लिए, Material Design के ज़रिए इस पैटर्न का इस्तेमाल किया जाता है:
.mdc-textfield-outline {
border-color: var(--mdc-theme-primary, /* default value */ #...);
}
.mdc-textfield--input {
caret-color: var(--mdc-theme-primary, #...);
}
इसके बाद, उपयोगकर्ता कस्टम प्रॉपर्टी वैल्यू लागू करके साइट की थीम बदल सकता है:
html {
--mdc-theme-primary: #F00;
}
html[dark] {
--mdc-theme-primary: #F88;
}
अगर टॉप-डाउन थीमिंग ज़रूरी है और आपको स्टाइल दिखाने में समस्या आ रही है, तो createRenderRoot
को बदलकर शैडो DOM को कभी भी बंद किया जा सकता है. ऐसा करने पर, this
को वापस पाने में मदद मिलेगी. इससे आपके कॉम्पोनेंट रेंडर हो जाएंगे टेंप्लेट को कस्टम एलिमेंट के साथ जोड़े जाने वाले शैडो रूट से जोड़ने के बजाय, उस एलिमेंट को कस्टम एलिमेंट से जोड़ें. इसके बाद, ये चीज़ें मिट जाएंगी: स्टाइल एनकैप्सुलेशन, डीओएम एनकैप्सुलेशन, और स्लॉट.
प्रोडक्शन
IE 11
अगर आपको IE 11 जैसे पुराने ब्राउज़र के लिए सहायता चाहिए, तो आपको कुछ पॉलीफ़िल लोड करने होंगे, जो करीब 33 केबी के हो जाते हैं. इस बारे में ज़्यादा जानकारी यहां मिल सकती है.
कंडिशनल बंडल
Lit की टीम दो अलग-अलग बंडल चुनने का सुझाव देती है, एक IE 11 के लिए और दूसरा आधुनिक ब्राउज़र के लिए. इसके कई फ़ायदे हैं:
- ES 6 में तेज़ी से काम किया जा सकता है और यह आपके ज़्यादातर क्लाइंट को सेवा देगा
- ट्रांसमिट किया गया ES 5, बंडल का साइज़ काफ़ी बढ़ा देता है
- शर्त वाले बंडल आपको दोनों का सर्वश्रेष्ठ देते हैं
- IE 11 सहायता
- आधुनिक ब्राउज़र पर कोई धीमा नहीं है
शर्तों के साथ पेश किए जाने वाले बंडल बनाने के तरीके के बारे में ज़्यादा जानकारी, हमारी दस्तावेज़ की साइट पर यहां मिल सकती है.