1. परिचय
Lit क्या है
Lit एक आसान लाइब्रेरी है. इसकी मदद से, तेज़ और हल्के वेब कॉम्पोनेंट बनाए जा सकते हैं. ये कॉम्पोनेंट किसी भी फ़्रेमवर्क में काम करते हैं. इसके अलावा, इन्हें बिना किसी फ़्रेमवर्क के भी इस्तेमाल किया जा सकता है. Lit की मदद से, शेयर किए जा सकने वाले कॉम्पोनेंट, ऐप्लिकेशन, डिज़ाइन सिस्टम वगैरह बनाए जा सकते हैं.
आपको क्या सीखने को मिलेगा
React के कई कॉन्सेप्ट को Lit में ट्रांसलेट करने का तरीका. जैसे:
- JSX और टेंप्लेटिंग
- कॉम्पोनेंट और प्रॉप
- स्टेट और लाइफ़साइकल
- हुक
- बच्चे
- Refs
- Mediating State
आपको क्या बनाना है
इस कोडलैब के आखिर में, React कॉम्पोनेंट के कॉन्सेप्ट को Lit के ऐनलॉग में बदला जा सकेगा.
आपको किन चीज़ों की ज़रूरत होगी
- Chrome, Safari, Firefox या Edge का नया वर्शन.
- एचटीएमएल, सीएसएस, JavaScript, और Chrome DevTools की जानकारी.
- React की जानकारी
- (ऐडवांस) अगर आपको डेवलपमेंट का सबसे अच्छा अनुभव चाहिए, तो VS Code डाउनलोड करें. आपको VS Code के लिए lit-plugin और NPM की भी ज़रूरत होगी.
2. Lit बनाम React
Lit के मुख्य कॉन्सेप्ट और क्षमताएं, कई मामलों में React के जैसी ही होती हैं. हालांकि, Lit में कुछ मुख्य अंतर भी होते हैं:
यह छोटा है
Lit बहुत छोटा है: यह React + ReactDOM के 40 से ज़्यादा केबी की तुलना में, करीब 5 केबी का है.

यह तेज़ है
सार्वजनिक बेंचमार्क में, Lit के टेंप्लेटिंग सिस्टम, lit-html की तुलना React के VDOM से की गई है. इसमें बताया गया है कि सबसे खराब स्थिति में, lit-html, React से 8 से 10% ज़्यादा तेज़ है. साथ ही, ज़्यादातर मामलों में, यह 50%से ज़्यादा तेज़ है.
LitElement (Lit की कॉम्पोनेंट बेस क्लास) से lit-html पर कम असर पड़ता है. हालांकि, कॉम्पोनेंट की सुविधाओं की तुलना करने पर, यह React की परफ़ॉर्मेंस से 16 से 30%बेहतर है. जैसे, मेमोरी का इस्तेमाल, इंटरैक्शन, और शुरू होने में लगने वाला समय.

इसके लिए, बिल्ड की ज़रूरत नहीं होती
ES मॉड्यूल और टैग किए गए टेंप्लेट लिटरल जैसी नई ब्राउज़र सुविधाओं की मदद से, Lit को रन करने के लिए कंपाइल करने की ज़रूरत नहीं होती. इसका मतलब है कि स्क्रिप्ट टैग, ब्राउज़र, और सर्वर की मदद से डेवलपमेंट एनवायरमेंट सेट अप किए जा सकते हैं.
ES मॉड्यूल और Skypack या UNPKG जैसे आधुनिक सीडीएन के साथ, आपको शुरू करने के लिए NPM की ज़रूरत भी नहीं पड़ सकती!
हालांकि, अगर आपको लिट कोड बनाना और उसे ऑप्टिमाइज़ करना है, तो अब भी ऐसा किया जा सकता है. नेटिव ES मॉड्यूल के लिए, डेवलपर के हाल ही के कंसोलिडेशन से Lit को फ़ायदा हुआ है. Lit सिर्फ़ सामान्य JavaScript है और इसके लिए, फ़्रेमवर्क के हिसाब से सीएलआई या बिल्ड हैंडलिंग की ज़रूरत नहीं होती.
फ़्रेमवर्क से अलग
Lit के कॉम्पोनेंट, वेब कॉम्पोनेंट कहे जाने वाले वेब स्टैंडर्ड के सेट पर आधारित होते हैं. इसका मतलब है कि Lit में कॉम्पोनेंट बनाने से, मौजूदा और आने वाले समय के फ़्रेमवर्क में काम किया जा सकेगा. अगर यह एचटीएमएल एलिमेंट के साथ काम करता है, तो यह वेब कॉम्पोनेंट के साथ भी काम करता है.
फ़्रेमवर्क इंटरऑप से जुड़ी समस्याएं सिर्फ़ तब होती हैं, जब फ़्रेमवर्क में DOM के लिए सीमित तौर पर सहायता उपलब्ध होती है. React ऐसा ही एक फ़्रेमवर्क है. हालांकि, यह Refs के ज़रिए एस्केप हैच की अनुमति देता है. साथ ही, React में Refs, डेवलपर के लिए अच्छा अनुभव नहीं है.
Lit टीम, @lit-labs/react नाम के एक एक्सपेरिमेंटल प्रोजेक्ट पर काम कर रही है. यह आपके Lit कॉम्पोनेंट को अपने-आप पार्स करेगा और एक React रैपर जनरेट करेगा, ताकि आपको रेफ़रंस का इस्तेमाल न करना पड़े.
इसके अलावा, Custom Elements Everywhere से आपको यह पता चलेगा कि कौनसे फ़्रेमवर्क और लाइब्रेरी, कस्टम एलिमेंट के साथ अच्छी तरह से काम करती हैं!
TypeScript के साथ बेहतर तरीके से काम करता है
हालांकि, JavaScript में Lit का पूरा कोड लिखा जा सकता है, लेकिन Lit को TypeScript में लिखा गया है. साथ ही, Lit की टीम का सुझाव है कि डेवलपर भी TypeScript का इस्तेमाल करें!
Lit टीम, Lit कम्यूनिटी के साथ मिलकर ऐसे प्रोजेक्ट को बनाए रखने के लिए काम कर रही है जो Lit टेंप्लेट में TypeScript टाइप की जांच और इंटेलिसेंस की सुविधा देते हैं. ये सुविधाएं, डेवलपमेंट और बिल्ड टाइम, दोनों के लिए lit-analyzer और lit-plugin के साथ उपलब्ध होती हैं.


डेवलपर टूल, ब्राउज़र में पहले से मौजूद होते हैं
Lit कॉम्पोनेंट, DOM में सिर्फ़ एचटीएमएल एलिमेंट होते हैं. इसका मतलब है कि अपने कॉम्पोनेंट की जांच करने के लिए, आपको अपने ब्राउज़र के लिए किसी भी टूल या एक्सटेंशन को इंस्टॉल करने की ज़रूरत नहीं है.
इसके लिए, आपको सिर्फ़ DevTools खोलना होगा. इसके बाद, कोई एलिमेंट चुनें और उसकी प्रॉपर्टी या स्थिति देखें.

इसे सर्वर साइड रेंडरिंग (एसएसआर) को ध्यान में रखकर बनाया गया है
Lit 2 को SSR के साथ काम करने के लिए बनाया गया है. इस कोडलैब को लिखते समय, Lit टीम ने अब तक SSR टूल को स्टेबल फ़ॉर्म में रिलीज़ नहीं किया है. हालांकि, Lit टीम पहले ही Google के सभी प्रॉडक्ट में सर्वर साइड रेंडर किए गए कॉम्पोनेंट को डिप्लॉय कर चुकी है. साथ ही, React ऐप्लिकेशन में SSR की जांच कर चुकी है. Lit टीम को उम्मीद है कि वह इन टूल को जल्द ही GitHub पर रिलीज़ कर देगी.
इस बीच, Lit टीम की प्रोग्रेस के बारे में जानने के लिए यहां जाएं.
इसमें कम निवेश करना पड़ता है
Lit का इस्तेमाल करने के लिए, आपको बहुत ज़्यादा समय देने की ज़रूरत नहीं है! Lit में कॉम्पोनेंट बनाए जा सकते हैं और उन्हें अपने मौजूदा प्रोजेक्ट में जोड़ा जा सकता है. अगर आपको ये पसंद नहीं हैं, तो आपको पूरे ऐप्लिकेशन को एक साथ बदलने की ज़रूरत नहीं है, क्योंकि वेब कॉम्पोनेंट अन्य फ़्रेमवर्क में भी काम करते हैं!
क्या आपने पूरा ऐप्लिकेशन Lit में बनाया है और अब आपको किसी दूसरी लाइब्रेरी का इस्तेमाल करना है? ऐसे में, अपने मौजूदा Lit ऐप्लिकेशन को नए फ़्रेमवर्क में रखा जा सकता है. साथ ही, अपनी पसंद के मुताबिक कॉन्टेंट को नए फ़्रेमवर्क के कॉम्पोनेंट में माइग्रेट किया जा सकता है.
इसके अलावा, कई मॉडर्न फ़्रेमवर्क, वेब कॉम्पोनेंट में आउटपुट देने की सुविधा के साथ काम करते हैं. इसका मतलब है कि वे आम तौर पर, Lit एलिमेंट के अंदर फ़िट हो सकते हैं.
3. Playground को सेट अप करना और उसे एक्सप्लोर करना
इस कोडलैब को पूरा करने के दो तरीके हैं:
- इसे पूरी तरह से ऑनलाइन किया जा सकता है. इसके लिए, ब्राउज़र का इस्तेमाल करें
- (ऐडवांस) VS Code का इस्तेमाल करके, इसे अपनी लोकल मशीन पर किया जा सकता है
कोड ऐक्सेस करना
इस कोडलैब में, Lit के प्लेग्राउंड के लिंक इस तरह दिए गए होंगे:
प्लेग्राउंड एक कोड सैंडबॉक्स है, जो पूरी तरह से आपके ब्राउज़र में चलता है. यह TypeScript और JavaScript फ़ाइलों को कंपाइल और चला सकता है. साथ ही, यह नोड मॉड्यूल में इंपोर्ट की गई फ़ाइलों को अपने-आप रिज़ॉल्व भी कर सकता है. उदाहरण के लिए,
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://cdn.skypack.dev/lit';
इस पूरे ट्यूटोरियल को Lit playground में किया जा सकता है. इसके लिए, इन चेकपॉइंट को शुरुआती पॉइंट के तौर पर इस्तेमाल करें. अगर VS Code का इस्तेमाल किया जा रहा है, तो इन चेकपॉइंट का इस्तेमाल करके किसी भी चरण के लिए शुरुआती कोड डाउनलोड किया जा सकता है. साथ ही, इनका इस्तेमाल अपने काम की जांच करने के लिए भी किया जा सकता है.
लाइट वाले प्लेग्राउंड के यूज़र इंटरफ़ेस (यूआई) के बारे में जानकारी

Lit Playground के यूज़र इंटरफ़ेस (यूआई) के इस स्क्रीनशॉट में, उन सेक्शन को हाइलाइट किया गया है जिनका इस्तेमाल इस कोडलैब में किया जाएगा.
- फ़ाइल चुनने वाला टूल. प्लस बटन पर ध्यान दें...
- फ़ाइल एडिटर.
- कोड की झलक.
- 'फिर से लोड करें' बटन.
- 'डाउनलोड करें' बटन.
VS Code सेटअप करना (ऐडवांस)
VS Code के इस सेटअप का इस्तेमाल करने के ये फ़ायदे हैं:
- टेंप्लेट टाइप की जांच करना
- टेंप्लेट के लिए इंटेलिसेंस और अपने-आप पूरा होने की सुविधा
अगर आपने पहले से ही NPM और VS Code (lit-plugin प्लग इन के साथ) इंस्टॉल कर लिया है और आपको उस एनवायरमेंट का इस्तेमाल करना आता है, तो इन प्रोजेक्ट को डाउनलोड करके शुरू किया जा सकता है. इसके लिए, यह तरीका अपनाएं:
- 'डाउनलोड करें' बटन दबाएं
- टार फ़ाइल के कॉन्टेंट को किसी डायरेक्ट्री में एक्सट्रैक्ट करना
- (अगर TS) quick tsconfig सेट अप करें, जो ES मॉड्यूल और es2015+ को आउटपुट करता है
- एक ऐसा डेवलपमेंट सर्वर इंस्टॉल करें जो बेयर मॉड्यूल स्पेसिफ़ायर को हल कर सके. Lit टीम, @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 और Lit टेंप्लेट
JSX, JavaScript का सिंटैक्स एक्सटेंशन है. इससे React का इस्तेमाल करने वाले लोग, अपने JavaScript कोड में आसानी से टेंप्लेट लिख पाते हैं. लिट टेंप्लेट भी इसी मकसद को पूरा करते हैं. ये किसी कॉम्पोनेंट के यूज़र इंटरफ़ेस (यूआई) को उसकी स्थिति के फ़ंक्शन के तौर पर दिखाते हैं.
बेसिक सिंटैक्स
React में, Hello World को इस तरह से रेंडर किया जाता है:
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
);
ऊपर दिए गए उदाहरण में, दो एलिमेंट और शामिल किया गया "name" वैरिएबल है. Lit में आपको यह करना होगा:
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 कहा जाता है. उदाहरण के लिए, 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
);
लिट TemplateResults, ऐरे, स्ट्रिंग, अन्य TemplateResults, और डायरेक्टिव स्वीकार कर सकते हैं.
अभ्यास के लिए, यहां दिए गए React कोड को 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 के सिंटैक्स के बीच सबसे बड़े अंतरों में से एक, डेटा बाइंडिंग सिंटैक्स है. उदाहरण के लिए, बाइंडिंग के साथ इस React इनपुट को लें:
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") पर सेट किया जाता है - डिफ़ॉल्ट वैल्यू सेट करता है
Lit में आपको यह करना होगा:
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
);
Lit के उदाहरण में, 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)के बराबर- यह बुनियादी वैल्यू, स्टाइल के नियमों के सिलेक्टर, और querySelector के लिए अच्छा है
पासिंग हैंडलर
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
);
ऊपर दिए गए उदाहरण में, एक इनपुट तय किया गया है. यह इनपुट ये काम करता है:
- जब इनपुट पर क्लिक किया जाता है, तब "click" शब्द को लॉग करें
- जब उपयोगकर्ता कोई वर्ण टाइप करता है, तब इनपुट की वैल्यू को लॉग करें
Lit में आपको यह करना होगा:
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
);
Lit के उदाहरण में, click इवेंट में @click के साथ एक लिसनर जोड़ा गया है.
इसके बाद, onChange का इस्तेमाल करने के बजाय, <input> के नेटिव input इवेंट से बाइंडिंग होती है, क्योंकि नेटिव change इवेंट सिर्फ़ blur पर ट्रिगर होता है (React इन इवेंट को ऐब्स्ट्रैक्ट करता है).
Lit इवेंट हैंडलर का सिंटैक्स
html`<my-element @event-name=${() => {...}}></my-element>`;
@प्रीफ़िक्स, इवेंट लिसनर के लिए बाइंडिंग सिंटैक्स हैinputRef.addEventListener('event-name', ...)के बराबर- नेटिव डीओएम इवेंट के नामों का इस्तेमाल करता है
5. कॉम्पोनेंट और प्रॉप
इस सेक्शन में, आपको Lit क्लास कॉम्पोनेंट और फ़ंक्शन के बारे में जानकारी मिलेगी. स्टेट और हुक के बारे में ज़्यादा जानकारी, बाद के सेक्शन में दी गई है.
क्लास कॉम्पोनेंट और LitElement
React क्लास कॉम्पोनेंट के बराबर Lit कॉम्पोनेंट, LitElement है. साथ ही, Lit की "रीऐक्टिव प्रॉपर्टी" का कॉन्सेप्ट, React के props और state का कॉम्बिनेशन है. उदाहरण के लिए:
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टीएस डेकोरेटर की तरह ही काम करता है, लेकिन 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
);
Lit में यह इस तरह दिखेगा:
import {html, render} from 'lit';
function Welcome(props) {
return html`<h1>Hello, ${props.name}</h1>`;
}
render(
Welcome({name: 'Elliott'}),
document.body.querySelector('#root')
);
6. स्टेट और लाइफ़साइकल
इस सेक्शन में, आपको Lit के स्टेट और लाइफ़साइकल के बारे में जानकारी मिलेगी.
राज्य
Lit में "रिएक्टिव प्रॉपर्टी" का कॉन्सेप्ट, React के स्टेट और प्रॉप्स का मिक्सचर है. बदलाव होने पर, रिएक्टिव प्रॉपर्टी कॉम्पोनेंट के लाइफ़साइकल को ट्रिगर कर सकती हैं. रीऐक्टिव प्रॉपर्टी दो तरह की होती हैं:
सार्वजनिक रिऐक्टिव प्रॉपर्टी
// 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 के props और state की तरह ही, लेकिन इसमें बदलाव किया जा सकता है
- यह एक सार्वजनिक एपीआई है. इसे कॉम्पोनेंट के उपभोक्ता ऐक्सेस और सेट करते हैं
इंटरनल रिएक्टिव स्टेट
// 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 का लाइफ़साइकल, React के लाइफ़साइकल से काफ़ी मिलता-जुलता है. हालांकि, इन दोनों में कुछ खास अंतर हैं.
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';
}
}
- Lit के बराबर भी
constructorहै - सुपर कॉल में कुछ भी पास करने की ज़रूरत नहीं है
- इनके ज़रिए शुरू किया गया (पूरी तरह से शामिल नहीं है):
document.createElementdocument.innerHTMLnew ComponentClass()- अगर पेज पर अपग्रेड नहीं किया गया टैग मौजूद है और उसकी परिभाषा
@customElementयाcustomElements.defineके साथ लोड और रजिस्टर की गई है
- React के
constructorफ़ंक्शन की तरह काम करता है
render
// React
render() {
return <div>Hello World</div>
}
// Lit
render() {
return html`<div>Hello World</div>`;
}
- Lit के बराबर भी
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, {...});
}
- इस फ़ंक्शन को पहली बार तब कॉल किया जाता है, जब कॉम्पोनेंट के टेंप्लेट को कॉम्पोनेंट के रूट में रेंडर किया जाता है
- इसे सिर्फ़ तब कॉल किया जाएगा, जब एलिमेंट कनेक्ट हो. उदाहरण के लिए, जब तक नोड को DOM ट्री में नहीं जोड़ा जाता, तब तक इसे
document.createElement('my-component')के ज़रिए कॉल नहीं किया जाता - यह कॉम्पोनेंट सेटअप करने के लिए सबसे सही जगह है. इसके लिए, कॉम्पोनेंट से रेंडर किए गए DOM की ज़रूरत होती है
- React के उलट,
firstUpdatedमें रिएक्टिव प्रॉपर्टी मेंcomponentDidMountबदलाव करने से, फिर से रेंडर होगा. हालांकि, ब्राउज़र आम तौर पर बदलावों को एक ही फ़्रेम में बैच करेगा. अगर उन बदलावों के लिए रूट के DOM को ऐक्सेस करने की ज़रूरत नहीं है, तो उन्हें आम तौर परwillUpdateमें शामिल किया जाना चाहिए
connectedCallback
// React
componentDidMount() {
this.window.addEventListener('resize', this.boundOnResize);
}
// Lit
connectedCallback() {
super.connectedCallback();
this.window.addEventListener('resize', this.boundOnResize);
}
- यह तब कॉल किया जाता है, जब कस्टम एलिमेंट को DOM ट्री में डाला जाता है
- React कॉम्पोनेंट के उलट, जब कस्टम एलिमेंट को DOM से अलग किया जाता है, तो उन्हें डिस्ट्रॉय नहीं किया जाता. इसलिए, उन्हें कई बार "कनेक्ट" किया जा सकता है
firstUpdatedको फिर से कॉल नहीं किया जाएगा
- यह डीओएम को फिर से शुरू करने या डिसकनेक्ट होने पर हटाए गए इवेंट लिसनर को फिर से अटैच करने के लिए उपयोगी है
- ध्यान दें:
connectedCallbackकोfirstUpdatedसे पहले कॉल किया जा सकता है. इसलिए, पहली बार कॉल करने पर डीओएम उपलब्ध नहीं हो सकता है
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को शुरुआती रेंडर पर भी कॉल किया जाता है - React के
componentDidUpdateफ़ंक्शन की तरह काम करता है
componentWillUnmount
// React
componentWillUnmount() {
this.window.removeEventListener('resize', this.boundOnResize);
}
// Lit
disconnectedCallback() {
super.disconnectedCallback();
this.window.removeEventListener('resize', this.boundOnResize);
}
- Lit equivalent,
disconnectedCallbackके जैसा होता है - React कॉम्पोनेंट के उलट, कस्टम एलिमेंट को डीओएम से अलग करने पर कॉम्पोनेंट डिस्ट्रॉय नहीं होता
componentWillUnmountके उलट,disconnectedCallbackको एलिमेंट को ट्री से हटाने के बाद कॉल किया जाता है- रूट के अंदर मौजूद डीओएम अब भी रूट के सबट्री से जुड़ा है
- यह इवेंट लिसनर और लीक हुए रेफ़रंस को हटाने के लिए उपयोगी है, ताकि ब्राउज़र कॉम्पोनेंट को गार्बेज कलेक्ट कर सके
कसरत
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 को लागू करने का तरीका बताया गया है. फिर से, लिट ऐनलॉग, firstUpdated और connectedCallback का मिश्रण होता है. इस कॉम्पोनेंट के मामले में, tick को setInterval के साथ कॉल करने के लिए, रूट के अंदर डीओएम को ऐक्सेस करने की ज़रूरत नहीं होती. इसके अलावा, जब एलिमेंट को दस्तावेज़ ट्री से हटा दिया जाता है, तब इंटरवल हट जाता है. इसलिए, अगर इसे फिर से अटैच किया जाता है, तो इंटरवल को फिर से शुरू करना होगा. इसलिए, यहां 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. हुक
इस सेक्शन में, आपको React Hook के कॉन्सेप्ट को Lit में ट्रांसलेट करने का तरीका बताया जाएगा.
React हुक के कॉन्सेप्ट
React हुक, फ़ंक्शन कॉम्पोनेंट को स्टेट में "हुक" करने का तरीका उपलब्ध कराते हैं. इसके कई फ़ायदे हैं.
- ये स्टेटफ़ुल लॉजिक को दोबारा इस्तेमाल करने की प्रोसेस को आसान बनाते हैं
- किसी कॉम्पोनेंट को छोटे-छोटे फ़ंक्शन में बांटने में मदद करना
इसके अलावा, फ़ंक्शन के आधार पर कॉम्पोनेंट बनाने पर फ़ोकस करने से, React के क्लास-आधारित सिंटैक्स से जुड़ी कुछ समस्याएं हल हो गईं. जैसे:
constructorसेsuperतकpropsको पास करनाconstructor- में प्रॉपर्टी को सही तरीके से सेट न करना
- React टीम ने उस समय यह वजह बताई थी, लेकिन ES2019 ने इसे ठीक कर दिया
thisअब कॉम्पोनेंट से जुड़ा नहीं है, इस वजह से होने वाली समस्याएं
Lit में React हुक के कॉन्सेप्ट
कॉम्पोनेंट और प्रॉप्स सेक्शन में बताया गया है कि 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ज़्यादातर मामलों में, कस्टम एलिमेंट के रेफ़रंस को दिखाता है- क्लास प्रॉपर्टी को अब क्लास मेंबर के तौर पर इंस्टैंटिएट किया जा सकता है. इससे कंस्ट्रक्टर पर आधारित लागू करने की प्रोसेस आसान हो जाती है
रिऐक्टिव कंट्रोलर
Hooks के पीछे मौजूद मुख्य कॉन्सेप्ट, Lit में reactive controllers के तौर पर मौजूद होते हैं. रिएक्टिव कंट्रोलर पैटर्न की मदद से, स्टेटफ़ुल लॉजिक शेयर किया जा सकता है. साथ ही, कॉम्पोनेंट को छोटे-छोटे मॉड्यूलर हिस्सों में बांटा जा सकता है. इसके अलावा, किसी एलिमेंट के अपडेट लाइफ़साइकल में हुक किया जा सकता है.
रिएक्टिव कंट्रोलर एक ऑब्जेक्ट इंटरफ़ेस होता है. यह 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 इंटरफ़ेस शेयर करता हो. हालांकि, Lit टीम ज़्यादातर बुनियादी मामलों के लिए, constructor वाली क्लास का इस्तेमाल करना पसंद करती है. यह क्लास, ReactiveControllerHost इंटरफ़ेस के साथ-साथ कंट्रोलर को शुरू करने के लिए ज़रूरी अन्य प्रॉपर्टी भी ले सकती है.
अब आपको React के लाइफ़साइकल कॉलबैक को कंट्रोलर कॉलबैक में बदलना होगा. कम शब्दों में:
componentDidMount- LitElement के
connectedCallback - कंट्रोलर के
hostConnectedपर
- LitElement के
ComponentWillUnmount- LitElement के
disconnectedCallback - कंट्रोलर के
hostDisconnectedपर
- LitElement के
React के लाइफ़साइकल को Lit के लाइफ़साइकल में बदलने के बारे में ज़्यादा जानने के लिए, स्टेट और लाइफ़साइकल सेक्शन देखें.
इसके बाद, 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. बच्चे
इस सेक्शन में, Lit में बच्चों को मैनेज करने के लिए स्लॉट इस्तेमाल करने का तरीका बताया गया है.
स्लॉट और बच्चे
स्लॉट की मदद से, कॉम्पोनेंट को नेस्ट किया जा सकता है. इससे कंपोज़िशन की सुविधा मिलती है.
React में, बच्चों को प्रॉप्स के ज़रिए इनहेरिट किया जाता है. डिफ़ॉल्ट स्लॉट props.children है और render फ़ंक्शन यह तय करता है कि डिफ़ॉल्ट स्लॉट कहां रखा गया है. उदाहरण के लिए:
const MyArticle = (props) => {
return <article>{props.children}</article>;
};
ध्यान रखें कि props.children, React कॉम्पोनेंट हैं, न कि एचटीएमएल एलिमेंट.
Lit में, बच्चों को स्लॉट एलिमेंट के साथ रेंडर फ़ंक्शन में कंपोज़ किया जाता है. ध्यान दें कि बच्चों के लिए सूचनाएं, लाइव प्रतिक्रियाओं की तरह नहीं मिलती हैं. Lit में, चाइल्ड नोड ऐसे एचटीएमएल एलिमेंट होते हैं जो स्लॉट से जुड़े होते हैं. इस अटैचमेंट को अनुमान कहा जाता है.
@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>
`;
}
}
बच्चों को स्लॉट असाइन करना
React में, कॉम्पोनेंट की प्रॉपर्टी के ज़रिए बच्चों को स्लॉट असाइन किए जाते हैं. यहां दिए गए उदाहरण में, React एलिमेंट को headerChildren और sectionChildren प्रॉप्स में पास किया गया है.
const MyNewsArticle = () => {
return (
<MyArticle
headerChildren={<h3>Extry, Extry! Read all about it!</h3>}
sectionChildren={<p>Children are props in React!</p>}
/>
);
};
Lit में, बच्चों को 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>) नहीं है और कोई ऐसा स्लॉट नहीं है जिसमें name एट्रिब्यूट (जैसे, <slot name="foo">) है और वह कस्टम एलिमेंट के बच्चों (जैसे, <div slot="foo">) के slot एट्रिब्यूट से मेल खाता है, तो उस नोड को प्रोजेक्ट नहीं किया जाएगा और वह नहीं दिखेगा.
9. Refs
कभी-कभी, किसी डेवलपर को HTMLElement के एपीआई को ऐक्सेस करने की ज़रूरत पड़ सकती है.
इस सेक्शन में, आपको Lit में एलिमेंट रेफ़रंस पाने का तरीका बताया जाएगा.
React के रेफ़रंस
React कॉम्पोनेंट को फ़ंक्शन कॉल की सीरीज़ में ट्रांसपाइल किया जाता है. जब इसे लागू किया जाता है, तब यह वर्चुअल डीओएम बनाता है. इस वर्चुअल DOM को 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 कॉम्पोनेंट ये काम करेगा:
- खाली टेक्स्ट इनपुट और टेक्स्ट वाला बटन रेंडर करें
- बटन पर क्लिक करने पर, इनपुट पर फ़ोकस करें
शुरुआती रेंडर के बाद, React जनरेट किए गए HTMLInputElement को ref एट्रिब्यूट के ज़रिए inputRef.current पर सेट कर देगा.
@query की मदद से "संदर्भ" सुविधा का इस्तेमाल करना
Lit, ब्राउज़र के साथ काम करता है और ब्राउज़र की नेटिव सुविधाओं के ऊपर बहुत पतला ऐब्स्ट्रैक्शन बनाता है.
Lit में refs के बराबर React में, @query और @queryAll डेकोरेटर से मिला HTMLElement होता है.
@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डेकोरेटर का इस्तेमाल करके,MyElementपर प्रॉपर्टी तय करता है. इससेHTMLInputElementके लिए गेटर बनता है.- यह कुकी,
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. Mediating State
इस सेक्शन में, आपको Lit में कॉम्पोनेंट के बीच स्टेट को मैनेज करने का तरीका बताया जाएगा.
फिर से इस्तेमाल किए जा सकने वाले कॉम्पोनेंट
React, फ़ंक्शनल रेंडरिंग पाइपलाइन की तरह काम करता है. इसमें डेटा ऊपर से नीचे की ओर जाता है. माता-पिता, बच्चों को प्रॉप्स के ज़रिए स्टेट के बारे में बताते हैं. बच्चे, प्रॉप्स में मौजूद कॉलबैक की मदद से माता-पिता से बातचीत करते हैं.
const CounterButton = (props) => {
const label = props.step < 0
? `- ${-1 * props.step}`
: `+ ${props.step}`;
return (
<button
onClick={() =>
props.addToCounter(props.step)}>{label}</button>
);
};
ऊपर दिए गए उदाहरण में, React कॉम्पोनेंट ये काम करता है:
- यह फ़ंक्शन, वैल्यू
props.stepके आधार पर लेबल बनाता है. - यह +step या -step को लेबल के तौर पर इस्तेमाल करके बटन रेंडर करता है
- यह कॉम्पोनेंट, क्लिक करने पर
props.addToCounterकोprops.stepआर्ग्युमेंट के तौर पर कॉल करके पैरंट कॉम्पोनेंट को अपडेट करता है
हालांकि, Lit में कॉलबैक पास किए जा सकते हैं, लेकिन इसके सामान्य पैटर्न अलग-अलग होते हैं. ऊपर दिए गए उदाहरण में मौजूद React कॉम्पोनेंट को, यहां दिए गए उदाहरण में 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>
`;
}
}
ऊपर दिए गए उदाहरण में, Lit कॉम्पोनेंट ये काम करेगा:
- रिएक्टिव प्रॉपर्टी बनाना
step - क्लिक करने पर,
update-counterवैल्यू वालेupdate-counterनाम के कस्टम इवेंट को डिसपैच करनाstep
ब्राउज़र इवेंट, चाइल्ड एलिमेंट से पैरंट एलिमेंट तक बबल अप होते हैं. इवेंट की मदद से, बच्चे इंटरैक्शन इवेंट और स्थिति में हुए बदलावों को ब्रॉडकास्ट कर सकते हैं. React, स्टेट को दूसरी दिशा में पास करता है. इसलिए, React कॉम्पोनेंट को Lit कॉम्पोनेंट की तरह ही इवेंट डिसपैच और सुनने के लिए इस्तेमाल करना आम बात नहीं है.
स्टेटफ़ुल कॉम्पोनेंट
React में, स्टेट को मैनेज करने के लिए हुक का इस्तेमाल करना आम बात है. CounterButton कॉम्पोनेंट का फिर से इस्तेमाल करके, MyCounter कॉम्पोनेंट बनाया जा सकता है. ध्यान दें कि addToCounter को CounterButton के दोनों इंस्टेंस में कैसे पास किया जाता है.
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, हर क्लिक परstepके हिसाब सेcountको अपडेट करने के लिएaddToCounterका इस्तेमाल करता है.
Lit में भी MyCounter को इसी तरह से लागू किया जा सकता है. ध्यान दें कि addToCounter को counter-button में पास नहीं किया जाता है. इसके बजाय, कॉलबैक को पैरंट एलिमेंट पर @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>
Lit, आपके कॉम्पोनेंट की स्टाइल को उनके रूट तक सीमित कर देगा. इसका मतलब है कि स्टाइल, कॉम्पोनेंट के अंदर और बाहर नहीं दिखेंगी. स्टाइल को कॉम्पोनेंट में पास करने के लिए, Lit टीम सीएसएस कस्टम प्रॉपर्टी का इस्तेमाल करने का सुझाव देती है. ऐसा इसलिए, क्योंकि ये 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 फ़ंक्शन, टैग किए गए टेंप्लेट लिटरल का इनवोकेशन दिखाता है.
Lit में परफ़ॉर्मेंस से जुड़ी कई सुविधाएं मिलती हैं. इसकी वजह यह है कि टैग फ़ंक्शन में पास किए गए स्ट्रिंग ऐरे का पॉइंटर एक जैसा होता है. जैसा कि दूसरे console.log में दिखाया गया है. ब्राउज़र, हर टैग फ़ंक्शन इनवोकेशन पर नया strings ऐरे नहीं बनाता है, क्योंकि यह एक ही टेंप्लेट लिटरल का इस्तेमाल कर रहा है. इसका मतलब है कि यह एएसटी में एक ही जगह पर मौजूद है. इसलिए, Lit की बाइंडिंग, पार्सिंग, और टेंप्लेट कैशिंग, इन सुविधाओं का फ़ायदा उठा सकती है. इसके लिए, रनटाइम में ज़्यादा अंतर करने की ज़रूरत नहीं होती.
टैग किए गए टेंप्लेट लिटरल के इस बिल्ट-इन ब्राउज़र व्यवहार की वजह से, Lit को परफ़ॉर्मेंस के मामले में काफ़ी फ़ायदा मिलता है. ज़्यादातर वर्चुअल DOM, अपना ज़्यादातर काम JavaScript में करते हैं. हालांकि, टैग किए गए टेंप्लेट लिटरल, ब्राउज़र के C++ में ज़्यादातर अंतर करते हैं.
अगर आपको React या Preact के साथ एचटीएमएल टैग किए गए टेंप्लेट लिटरल का इस्तेमाल शुरू करना है, तो Lit टीम htm लाइब्रेरी का इस्तेमाल करने का सुझाव देती है.
हालांकि, Google Codelabs साइट और कई ऑनलाइन कोड एडिटर में, टैग किए गए टेंप्लेट लिटरल सिंटैक्स हाइलाइटिंग का इस्तेमाल बहुत कम किया जाता है. कुछ आईडीई और टेक्स्ट एडिटर में, ये सुविधाएं डिफ़ॉल्ट रूप से उपलब्ध होती हैं. जैसे, Atom और GitHub का कोडब्लॉक हाइलाइटर. Lit टीम, कम्यूनिटी के साथ मिलकर भी काम करती है. जैसे, lit-plugin जैसे प्रोजेक्ट को बनाए रखने के लिए. यह VS Code का एक प्लगिन है. यह आपके Lit प्रोजेक्ट में सिंटैक्स हाइलाइटिंग, टाइप चेकिंग, और इंटेलिसेंस की सुविधा जोड़ता है.
Lit & JSX + React DOM
JSX, ब्राउज़र में नहीं चलता. इसके बजाय, यह JSX को JavaScript फ़ंक्शन कॉल में बदलने के लिए प्रीप्रोसेसर का इस्तेमाल करता है. आम तौर पर, यह काम Babel के ज़रिए किया जाता है.
उदाहरण के लिए, Babel इसे बदल देगा:
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, React के आउटपुट को लेता है और उसे असल डीओएम में बदल देता है. इसमें प्रॉपर्टी, एट्रिब्यूट, इवेंट लिसनर वगैरह शामिल होते हैं.
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 में पारंपरिक वर्चुअल डीओएम का इस्तेमाल नहीं किया जाता है. इसके बजाय, सीधे तौर पर डीओएम एपीआई का इस्तेमाल किया जाता है. इसलिए, Lit 2 का साइज़, React (2.8 केबी) + react-dom (39.4 केबी) के 40 केबी के मुकाबले, 5 केबी से कम है.
इवेंट
React, सिंथेटिक इवेंट सिस्टम का इस्तेमाल करता है. इसका मतलब है कि react-dom को हर उस इवेंट को तय करना होगा जिसका इस्तेमाल हर कॉम्पोनेंट पर किया जाएगा. साथ ही, हर तरह के नोड के लिए, camelCase इवेंट लिसनर का इक्विवेलेंट उपलब्ध कराना होगा. इस वजह से, JSX में कस्टम इवेंट के लिए इवेंट लिसनर को तय करने का कोई तरीका नहीं है. इसलिए, डेवलपर को ref का इस्तेमाल करना होगा. इसके बाद, लिसनर को लागू करना होगा. इससे डेवलपर को खराब अनुभव मिलता है. ऐसा तब होता है, जब ऐसी लाइब्रेरी इंटिग्रेट की जाती हैं जिन्हें React को ध्यान में रखकर नहीं बनाया गया है. इसलिए, React के लिए खास तौर पर रैपर लिखना पड़ता है.
Lit-html सीधे तौर पर DOM को ऐक्सेस करता है और नेटिव इवेंट का इस्तेमाल करता है. इसलिए, इवेंट लिसनर को @event-name=${eventNameListener} की तरह आसानी से जोड़ा जा सकता है. इसका मतलब है कि इवेंट लिसनर जोड़ने के साथ-साथ इवेंट ट्रिगर करने के लिए, कम रनटाइम पार्सिंग की जाती है.
कॉम्पोनेंट और प्रॉप
React कॉम्पोनेंट और कस्टम एलिमेंट
LitElement, अपने कॉम्पोनेंट को पैकेज करने के लिए कस्टम एलिमेंट का इस्तेमाल करता है. कस्टम एलिमेंट, कॉम्पोनेंट बनाने के मामले में React कॉम्पोनेंट के बीच कुछ ट्रेडऑफ़ पेश करते हैं. स्टेट और लाइफ़साइकल सेक्शन में, स्टेट और लाइफ़साइकल के बारे में ज़्यादा जानकारी दी गई है.
कस्टम एलिमेंट के कॉम्पोनेंट सिस्टम के तौर पर इस्तेमाल करने के कुछ फ़ायदे:
- ये ब्राउज़र में पहले से मौजूद होते हैं और इनके लिए किसी टूल की ज़रूरत नहीं होती
innerHTMLऔरdocument.createElementसे लेकरquerySelectorतक, हर ब्राउज़र एपीआई में फ़िट हो जाता है- आम तौर पर, इसका इस्तेमाल सभी फ़्रेमवर्क में किया जा सकता है
customElements.defineके साथ लेज़ी तरीके से रजिस्टर किया जा सकता है और DOM को "हाइड्रेट" किया जा सकता है
React कॉम्पोनेंट की तुलना में, कस्टम एलिमेंट की कुछ कमियां:
- क्लास तय किए बिना कस्टम एलिमेंट नहीं बनाया जा सकता. इसलिए, JSX जैसे फ़ंक्शनल कॉम्पोनेंट नहीं बनाए जा सकते
- इसमें क्लोज़िंग टैग
- होना चाहिए
- ध्यान दें: डेवलपर के लिए आसानी से काम करने वाले ब्राउज़र वेंडर, अपने-आप बंद होने वाले टैग स्पेसिफ़िकेशन पर अफ़सोस करते हैं. यही वजह है कि नए स्पेसिफ़िकेशन में, अपने-आप बंद होने वाले टैग शामिल नहीं होते
- यह डीओएम ट्री में एक अतिरिक्त नोड जोड़ता है. इससे लेआउट से जुड़ी समस्याएं हो सकती हैं
- JavaScript के ज़रिए रजिस्टर किया गया हो
Lit ने कस्टम एलिमेंट को, खास एलिमेंट सिस्टम के मुकाबले ज़्यादा प्राथमिकता दी है. इसकी वजह यह है कि कस्टम एलिमेंट, ब्राउज़र में पहले से मौजूद होते हैं. साथ ही, Lit टीम का मानना है कि क्रॉस-फ़्रेमवर्क के फ़ायदे, कॉम्पोनेंट ऐब्स्ट्रैक्शन लेयर से मिलने वाले फ़ायदों से ज़्यादा होते हैं. असल में, Lit टीम ने lit-ssr स्पेस में काम करके, 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>
स्टेट और लाइफ़साइकल
React के अन्य लाइफ़साइकल कॉलबैक
static getDerivedStateFromProps
Lit में इसके जैसा कोई विकल्प नहीं है, क्योंकि props और state, दोनों एक ही क्लास प्रॉपर्टी हैं
shouldComponentUpdate
- लाइट के बराबर
shouldUpdateहै - React के उलट, इसे पहले रेंडर पर कॉल किया जाता है
- React के
shouldComponentUpdateफ़ंक्शन की तरह काम करता है
getSnapshotBeforeUpdate
Lit में, getSnapshotBeforeUpdate, update और willUpdate, दोनों से मिलता-जुलता है
willUpdate
updateसे पहले कॉल किया गयाgetSnapshotBeforeUpdateके उलट,willUpdateकोrenderसे पहले कॉल किया जाता हैwillUpdateमें मौजूद रिएक्टिव प्रॉपर्टी में किए गए बदलावों से, अपडेट साइकल फिर से ट्रिगर नहीं होती- यह ऐसी प्रॉपर्टी की वैल्यू का हिसाब लगाने के लिए सबसे सही जगह है जो दूसरी प्रॉपर्टी पर निर्भर करती हैं और जिनका इस्तेमाल अपडेट करने की बाकी प्रोसेस में किया जाता है
- इस तरीके को सर्वर पर SSR में कॉल किया जाता है. इसलिए, यहां DOM को ऐक्सेस करने का सुझाव नहीं दिया जाता
update
willUpdateके बाद कॉल किया गयाgetSnapshotBeforeUpdateके उलट,updateकोrenderसे पहले कॉल किया जाता है- अगर
super.updateको कॉल करने से पहलेupdateमें मौजूद रिएक्टिव प्रॉपर्टी में बदलाव किया जाता है, तो अपडेट साइकल फिर से ट्रिगर नहीं होती - यह कॉम्पोनेंट के आस-पास मौजूद डीओएम से जानकारी इकट्ठा करने के लिए एक अच्छी जगह है. ऐसा तब किया जाता है, जब रेंडर किए गए आउटपुट को डीओएम में सेव किया जाता है
- एसएसआर में, इस तरीके को सर्वर पर कॉल नहीं किया जाता है
Lit के अन्य लाइफ़साइकल कॉलबैक
लाइफ़साइकल के कई ऐसे कॉलबैक हैं जिनके बारे में पिछले सेक्शन में नहीं बताया गया है. ऐसा इसलिए है, क्योंकि 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 होगी.
Lit Update Lifecycle Visualization
अपडेट के लाइफ़साइकल के तीन हिस्से होते हैं:
- अपडेट से पहले
- अपडेट करें
- अपडेट के बाद
अपडेट से पहले

requestUpdate के बाद, शेड्यूल किया गया अपडेट बाकी है.
अपडेट करें

अपडेट के बाद

हुक
हुक क्यों
React में हुक इसलिए पेश किए गए थे, ताकि फ़ंक्शन कॉम्पोनेंट के उन इस्तेमाल के उदाहरणों को आसान बनाया जा सके जिनमें स्टेट की ज़रूरत होती है. कई सामान्य मामलों में, हुक वाले फ़ंक्शन कॉम्पोनेंट, क्लास कॉम्पोनेंट की तुलना में ज़्यादा आसान और पढ़ने में आसान होते हैं. हालांकि, एसिंक्रोनस स्टेट अपडेट के साथ-साथ हुक या इफ़ेक्ट के बीच डेटा पास करने के लिए, हुक पैटर्न काफ़ी नहीं होता. ऐसे में, क्लास पर आधारित समाधान, जैसे कि रिएक्टिव कंट्रोलर बेहतर होते हैं.
एपीआई अनुरोध हुक और कंट्रोलर
एपीआई से डेटा का अनुरोध करने के लिए, हुक लिखना आम बात है. उदाहरण के लिए, इस React फ़ंक्शन कॉम्पोनेंट को लें. यह कॉम्पोनेंट ये काम करता है:
index.tsx- टेक्स्ट रेंडर करता है
useAPIके जवाब को रेंडर करता है- यूज़र आईडी + उपयोगकर्ता का नाम
- गड़बड़ी का मैसेज
- जब उपयोगकर्ता 11 तक पहुंचता है, तब 404 गड़बड़ी दिखती है (डिज़ाइन के मुताबिक)
- अगर एपीआई फ़ेच करने की प्रोसेस बंद कर दी जाती है, तो गड़बड़ी का मैसेज दिखता है
- लोडिंग संदेश
- यह एक्सटेंशन, ऐक्शन बटन रेंडर करता है
- Next user: यह अगले उपयोगकर्ता के लिए एपीआई फ़ेच करता है
- रद्द करें: इससे एपीआई फ़ेच करने की प्रोसेस बंद हो जाती है और गड़बड़ी का मैसेज दिखता है
useApi.tsx- यह
useApiकस्टम हुक को तय करता है - यह कुकी, किसी एपीआई से उपयोगकर्ता ऑब्जेक्ट को एसिंक तरीके से फ़ेच करेगी
- यह इवेंट तब ट्रिगर होता है, जब:
- उपयोगकर्ता नाम
- क्या फ़ेच लोड हो रहा है
- गड़बड़ी के मैसेज
- फ़ेच करने की प्रोसेस को रोकने के लिए कॉलबैक
- अगर अनमाउंट किया जाता है, तो फ़ेच करने की प्रोसेस को बंद कर देता है
- यह
यहां Lit + Reactive Controller को लागू करने का तरीका बताया गया है.
सीखने वाली अहम बातें:
- रीऐक्टिव कंट्रोलर, कस्टम हुक की तरह होते हैं
- कॉलबैक और इफ़ेक्ट के बीच, रेंडर न किए जा सकने वाले डेटा को पास करना
- React,
useEffectऔरuseCallbackके बीच डेटा ट्रांसफ़र करने के लिएuseRefका इस्तेमाल करता है - Lit, प्राइवेट क्लास प्रॉपर्टी का इस्तेमाल करता है
- React, असल में किसी प्राइवेट क्लास प्रॉपर्टी के व्यवहार की नकल कर रहा है
- 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 इवेंट ट्रिगर होता है. Lit कॉम्पोनेंट, slotchange इवेंट के साथ इवेंट-लिसनर को बाइंड कर सकता है. नीचे दिए गए उदाहरण में, shadowRoot में मिले पहले स्लॉट के assignedNodes को slotchange पर कंसोल में लॉग किया जाएगा.
@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>
`;
}
}
Refs
रेफ़रंस जनरेट करना
Lit और React, दोनों ही अपने render फ़ंक्शन कॉल किए जाने के बाद, HTMLElement का रेफ़रंस दिखाते हैं. हालांकि, यह देखना ज़रूरी है कि React और Lit, DOM को कैसे कंपोज़ करते हैं. बाद में, इसे Lit @query डेकोरेटर या React रेफ़रंस के ज़रिए वापस किया जाता है.
React एक फ़ंक्शनल पाइपलाइन है, जो HTMLElements नहीं, बल्कि React कॉम्पोनेंट बनाती है. Ref को HTMLElement के रेंडर होने से पहले ही डिक्लेयर कर दिया जाता है. इसलिए, मेमोरी में एक स्पेस असाइन किया जाता है. इसलिए, आपको Ref की शुरुआती वैल्यू के तौर पर null दिखता है, क्योंकि असल DOM एलिमेंट अभी तक बनाया (या रेंडर) नहीं गया है. इसका मतलब है कि useRef(null).
जब ReactDOM, React कॉम्पोनेंट को 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()}
`;
}
}
Mediating State
React में, कॉलबैक का इस्तेमाल करने का तरीका यह है कि स्टेट को React खुद मैनेज करता है. React, एलिमेंट के ज़रिए दिए गए स्टेट पर भरोसा न करने की पूरी कोशिश करता है. डीओएम, रेंडरिंग प्रोसेस का एक असर है.
बाहरी स्थिति
Lit के साथ Redux, MobX या किसी अन्य स्टेट मैनेजमेंट लाइब्रेरी का इस्तेमाल किया जा सकता है.
Lit कॉम्पोनेंट, ब्राउज़र स्कोप में बनाए जाते हैं. इसलिए, ब्राउज़र के स्कोप में मौजूद कोई भी लाइब्रेरी, Lit के लिए उपलब्ध होती है. Lit में मौजूदा स्टेट मैनेजमेंट सिस्टम का इस्तेमाल करने के लिए, कई शानदार लाइब्रेरी बनाई गई हैं.
यहां Vaadin की सीरीज़ दी गई है. इसमें Lit कॉम्पोनेंट में Redux का इस्तेमाल करने का तरीका बताया गया है.
Adobe के lit-mobx को देखें. इससे आपको पता चलेगा कि बड़ी साइट, Lit में MobX का इस्तेमाल कैसे कर सकती है.
इसके अलावा, Apollo Elements देखें. इससे आपको पता चलेगा कि डेवलपर, अपने वेब कॉम्पोनेंट में GraphQL को कैसे शामिल कर रहे हैं.
Lit, ब्राउज़र की नेटिव सुविधाओं के साथ काम करता है. साथ ही, ब्राउज़र स्कोप में मौजूद ज़्यादातर स्टेट मैनेजमेंट समाधानों का इस्तेमाल, Lit कॉम्पोनेंट में किया जा सकता है.
शैलीकृत करना
शैडो डीओएम
Lit, किसी कस्टम एलिमेंट में स्टाइल और डीओएम को नेटिव तौर पर शामिल करने के लिए, शैडो डीओएम का इस्तेमाल करता है. शैडो रूट, मुख्य दस्तावेज़ ट्री से अलग शैडो ट्री जनरेट करते हैं. इसका मतलब है कि ज़्यादातर स्टाइल, इस दस्तावेज़ के लिए तय की गई हैं. हालांकि, कुछ स्टाइल लीक हो जाती हैं. जैसे, रंग और फ़ॉन्ट से जुड़ी अन्य स्टाइल.
शैडो डीओएम, सीएसएस स्पेसिफ़िकेशन में नए कॉन्सेप्ट और सिलेक्टर भी जोड़ता है:
: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 को बदलकर this करें. इससे आपके कॉम्पोनेंट का टेंप्लेट, कस्टम एलिमेंट से जुड़े शैडो रूट के बजाय कस्टम एलिमेंट में ही रेंडर होगा. इससे आपको ये सुविधाएं नहीं मिलेंगी: स्टाइल एनकैप्सुलेशन, डीओएम एनकैप्सुलेशन, और स्लॉट.
प्रोडक्शन
IE 11
अगर आपको IE 11 जैसे पुराने ब्राउज़र पर काम करना है, तो आपको कुछ पॉलीफ़िल लोड करने होंगे. इनका साइज़ करीब 33 केबी होता है. इस बारे में ज़्यादा जानकारी यहां मिल सकती है.
शर्तों के हिसाब से बंडल
Lit टीम का सुझाव है कि दो अलग-अलग बंडल दिखाए जाएं. एक IE 11 के लिए और दूसरा मॉडर्न ब्राउज़र के लिए. इसके कई फ़ायदे हैं:
- ES 6 का इस्तेमाल करने से, जवाब तेज़ी से मिलते हैं. साथ ही, इससे आपके ज़्यादातर क्लाइंट को जवाब मिल पाएंगे
- ES5 को ट्रांसपाइल करने से, बंडल का साइज़ काफ़ी बढ़ जाता है
- शर्तों के साथ बंडल किए गए ऑफ़र से आपको दोनों तरह के फ़ायदे मिलते हैं
- IE 11 के लिए सहायता
- मॉडर्न ब्राउज़र पर कोई असर नहीं पड़ता
शर्त के हिसाब से दिखाए जाने वाले बंडल बनाने के तरीके के बारे में ज़्यादा जानकारी, हमारी दस्तावेज़ साइट पर यहां मिल सकती है.