1. परिचय
पिछली बार अपडेट किए जाने की तारीख: 10-08-2021
वेब कॉम्पोनेंट
वेब कॉम्पोनेंट, वेब प्लैटफ़ॉर्म एपीआई का एक सेट है. इसकी मदद से, वेब पेजों और वेब ऐप्लिकेशन में इस्तेमाल करने के लिए, पसंद के मुताबिक, फिर से इस्तेमाल किए जा सकने वाले, और सभी एनकैप्सुलेट किए गए एचटीएमएल टैग बनाए जा सकते हैं. वेब कॉम्पोनेंट के स्टैंडर्ड पर बनाए गए कस्टम कॉम्पोनेंट और विजेट, सभी मॉडर्न ब्राउज़र पर काम करेंगे. इनका इस्तेमाल एचटीएमएल के साथ काम करने वाली किसी भी JavaScript लाइब्रेरी या फ़्रेमवर्क के साथ किया जा सकता है.
लिट क्या है
Lit, एक सामान्य लाइब्रेरी है. इसकी मदद से, कम साइज़ और तेज़ी से काम करने वाले ऐसे वेब कॉम्पोनेंट बनाए जा सकते हैं जो किसी भी फ़्रेमवर्क में या बिना किसी फ़्रेमवर्क के काम करते हैं. Lit की मदद से, शेयर किए जा सकने वाले कॉम्पोनेंट, ऐप्लिकेशन, डिज़ाइन सिस्टम वगैरह बनाए जा सकते हैं.
Lit, वेब कॉम्पोनेंट के सामान्य कामों को आसान बनाने के लिए एपीआई उपलब्ध कराता है. जैसे, प्रॉपर्टी, एट्रिब्यूट, और रेंडरिंग को मैनेज करना.
आपको इनके बारे में जानकारी मिलेगी
- वेब कॉम्पोनेंट क्या है
- वेब कॉम्पोनेंट के कॉन्सेप्ट
- वेब कॉम्पोनेंट बनाने का तरीका
- lit-html और LitElement क्या हैं
- Lit एक वेब कॉम्पोनेंट का इस्तेमाल कैसे करता है
आपको क्या बनाना होगा
- वैनिला पसंद / नापसंद करने वाला वेब कॉम्पोनेंट
- पसंद / नापसंद लिटर-आधारित वेब घटक
आपको इन चीज़ों की ज़रूरत होगी
- कोई भी अपडेट किया गया मॉडर्न ब्राउज़र (Chrome, Safari, Firefox, Chromium Edge). वेब कॉम्पोनेंट सभी मॉडर्न ब्राउज़र पर काम करते हैं. साथ ही, पॉलीफ़िल, Microsoft Internet Explorer 11 और बिना Chromium वाले Microsoft Edge के लिए उपलब्ध हैं.
- एचटीएमएल, सीएसएस, JavaScript, और Chrome DevTools के बारे में जानकारी.
2. सेट अप और प्लेग्राउंड को एक्सप्लोर करना
कोड ऐक्सेस करना
पूरे कोडलैब के दौरान, Lit के प्लेग्राउंड में इस तरह के लिंक दिखेंगे:
प्लेग्राउंड एक कोड सैंडबॉक्स होता है, जो आपके ब्राउज़र में पूरी तरह चलता है. यह TypeScript और JavaScript फ़ाइलों को कंपाइल और चला सकता है. साथ ही, यह नोड मॉड्यूल के इंपोर्ट को भी अपने-आप ठीक कर सकता है. उदाहरण के लिए,
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://unpkg.com/lit?module';
शुरुआती पॉइंट के तौर पर इन चेकपॉइंट का इस्तेमाल करके, Lit खेल के मैदान में पूरा ट्यूटोरियल किया जा सकता है. अगर आपने वीएस कोड का इस्तेमाल किया है, तो इन चेकपॉइंट का इस्तेमाल करके किसी भी चरण के लिए शुरुआती कोड डाउनलोड किया जा सकता है. साथ ही, इन चेकपॉइंट का इस्तेमाल करके अपने काम की जांच की जा सकती है.
रोशनी से जगमगाते प्लेग्राउंड यूआई को एक्सप्लोर करें
लिटिल प्लेग्राउंड यूज़र इंटरफ़ेस (यूआई) का स्क्रीनशॉट, उन सेक्शन को हाइलाइट करता है जिनका इस्तेमाल आपको इस कोडलैब में किया जाएगा.
- फ़ाइल चुनने वाला टूल. प्लस बटन को नोट करें...
- फ़ाइल संपादक.
- कोड की झलक.
- 'फिर से लोड करें' बटन.
- 'डाउनलोड करें' बटन.
बनाम कोड सेटअप (बेहतर)
बनाम इस बनाम कोड सेटअप का इस्तेमाल करने के फ़ायदे यहां दिए गए हैं:
- टेंप्लेट टाइप की जांच
- टेंप्लेट इंटेलिजेंस और अपने-आप पूरा होने की सुविधा
अगर आपके पास NPM, VS Code (lit-plugin प्लग इन के साथ) पहले से इंस्टॉल है और आपको उस एनवायरमेंट का इस्तेमाल करने का तरीका पता है, तो यहां दिए गए तरीके से इन प्रोजेक्ट को डाउनलोड करके शुरू किया जा सकता है:
- 'डाउनलोड करें' बटन दबाएं
- टार फ़ाइल के कॉन्टेंट को डायरेक्ट्री में निकालें
- ऐसा डेव सर्वर इंस्टॉल करें जो बेयर मॉड्यूल स्पेसिफ़िकेशन का समाधान कर सके (लिट टीम @web/dev-server का सुझाव देती है)
- यहां एक उदाहरण दिया गया है
package.json
- यहां एक उदाहरण दिया गया है
- डेव सर्वर चलाएं और अपना ब्राउज़र खोलें (अगर
@web/dev-server
का इस्तेमाल किया जा रहा है, तोnpx web-dev-server --node-resolve --watch --open
का इस्तेमाल किया जा सकता है)- अगर आपने
package.json
का इस्तेमाल किया है, तोnpm run serve
का इस्तेमाल करें
- अगर आपने
3. कस्टम एलिमेंट तय करें
कस्टम एलिमेंट
वेब कॉम्पोनेंट, चार नेटिव वेब एपीआई का कलेक्शन होते हैं. ये वजह हैं:
- ES मॉड्यूल
- कस्टम एलिमेंट
- शैडो डीओएम
- HTML टेम्प्लेट
आपने पहले ही ES मॉड्यूल की खास बातों का इस्तेमाल कर लिया है. इससे, आपको <script type="module">
के साथ पेज में लोड किए गए इंपोर्ट और एक्सपोर्ट के साथ JavaScript मॉड्यूल बनाने की सुविधा मिलती है.
कस्टम एलिमेंट तय करना
कस्टम एलिमेंट स्पेसिफ़िकेशन की मदद से, उपयोगकर्ता JavaScript का इस्तेमाल करके अपने एचटीएमएल एलिमेंट तय कर सकते हैं. नामों में हाइफ़न (-
) होना चाहिए, ताकि इन्हें ब्राउज़र के नेटिव एलिमेंट से अलग किया जा सके. index.js
फ़ाइल को मिटाएं और कस्टम एलिमेंट क्लास तय करें:
index.js
class RatingElement extends HTMLElement {}
customElements.define('rating-element', RatingElement);
कस्टम एलिमेंट, ऐसी क्लास को जोड़कर तय किया जाता है जो हाइफ़न वाले टैग के नाम के साथ HTMLElement
को बड़ा करती है. customElements.define
को किया जाने वाला कॉल, ब्राउज़र को क्लास RatingElement
को TagName ‘rating-element'
से जोड़ने के लिए कहता है. इसका मतलब है कि आपके दस्तावेज़ में <rating-element>
नाम का हर एलिमेंट इस क्लास से जोड़ा जाएगा.
दस्तावेज़ के मुख्य हिस्से में <rating-element>
लगाएं और देखें कि क्या रेंडर हो रहा है.
index.html
<body>
<rating-element></rating-element>
</body>
अब, आउटपुट को देखते हुए, आपको दिखेगा कि कोई भी रेंडर नहीं हुआ है. ऐसा इसलिए है, क्योंकि आपने ब्राउज़र को <rating-element>
को रेंडर करने का तरीका नहीं बताया है. Chrome Dev टूल में <rating-element>
को चुनकर, इस बात की पुष्टि की जा सकती है कि कस्टम एलिमेंट की परिभाषा पूरी हो गई है या नहीं एलिमेंट सिलेक्टर और कंसोल में, इन्हें कॉल करें:
$0.constructor
कौनसा आउटपुट देना चाहिए:
class RatingElement extends HTMLElement {}
कस्टम एलिमेंट की लाइफ़साइकल
कस्टम एलिमेंट में, लाइफ़साइकल हुक का एक सेट होता है. ये वजह हैं:
constructor
connectedCallback
disconnectedCallback
attributeChangedCallback
adoptedCallback
पहली बार एलिमेंट बनाए जाने पर, constructor
को कॉल किया जाता है: उदाहरण के लिए, document.createElement(‘rating-element')
या new RatingElement()
को कॉल करके. कंस्ट्रक्टर, आपके एलिमेंट को सेट अप करने की अच्छी जगह है. हालांकि, आम तौर पर "बूट-अप" एलिमेंट के लिए, कंस्ट्रक्टर में डीओएम हेर-फेर करना खराब तरीका माना जाता है परफ़ॉर्मेंस की वजहों से.
connectedCallback
को तब कॉल किया जाता है, जब कस्टम एलिमेंट डीओएम से अटैच होता है. आम तौर पर, शुरुआती डीओएम में बदलाव यहां होते हैं.
कस्टम एलिमेंट को डीओएम से हटाने के बाद, disconnectedCallback
को कॉल किया जाता है.
attributeChangedCallback(attrName, oldValue, newValue)
को तब कॉल किया जाता है, जब उपयोगकर्ताओं के लिए तय किए गए किसी भी एट्रिब्यूट में बदलाव होता है.
adoptedCallback
को तब कॉल किया जाता है, जब कस्टम एलिमेंट को adoptNode
के ज़रिए किसी दूसरे documentFragment
से मुख्य दस्तावेज़ में शामिल किया जाता है, जैसे कि HTMLTemplateElement
.
रेंडर डीओएम
अब कस्टम एलिमेंट पर वापस जाएं और उसके साथ कुछ DOM जोड़ें. एलिमेंट का कॉन्टेंट तब सेट करें, जब वह डीओएम से अटैच हो:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
this.innerHTML = `
<style>
rating-element {
display: inline-flex;
align-items: center;
}
rating-element button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
constructor
में, एलिमेंट में rating
नाम की इंस्टेंस प्रॉपर्टी सेव की जाती है. connectedCallback
में, मौजूदा रेटिंग दिखाने के लिए DOM चिल्ड्रेन को <rating-element>
में जोड़ा जाता है. साथ ही, उन्हें पसंद और नापसंद करने का बटन भी दिखाया जाता है.
4. शैडो डीओएम
शैडो डीओएम क्यों?
पिछले चरण में, आप देखेंगे कि आपने जो शैली टैग डाला है उसमें सिलेक्टर, पेज पर किसी भी रेटिंग एलिमेंट के साथ-साथ किसी भी बटन को चुनते हैं. इसकी वजह से, एलिमेंट से स्टाइल लीक हो सकते हैं और ऐसे अन्य नोड चुन लिए जा सकते हैं जिन्हें शायद आप स्टाइल न करना चाहें. इसके अलावा, इस कस्टम एलिमेंट के बाहर की अन्य स्टाइल, आपके कस्टम एलिमेंट के अंदर के नोड को अनजाने में स्टाइल कर सकती हैं. उदाहरण के लिए, मुख्य दस्तावेज़ के सबसे ऊपर स्टाइल टैग लगाने की कोशिश करें:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="./index.js" type="module"></script>
<style>
span {
border: 1px solid red;
}
</style>
</head>
<body>
<rating-element></rating-element>
</body>
</html>
आपके आउटपुट में रेटिंग के लिए स्पैन के चारों ओर लाल रंग का बॉर्डर बॉक्स होना चाहिए. यह एक मामूली बात है, लेकिन DOM एनकैप्सुलेशन की कमी की वजह से ज़्यादा जटिल ऐप्लिकेशन के लिए बड़ी समस्याएं आ सकती हैं. ऐसे में शैडो डीओएम काम करता है.
शैडो रूट को अटैच करना
एलिमेंट में शैडो रूट अटैच करें और उस रूट के अंदर DOM को रेंडर करें:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
पेज को रीफ़्रेश करने पर, आपको दिखेगा कि मुख्य दस्तावेज़ की स्टाइल, शैडो रूट के अंदर के नोड को नहीं चुन सकती.
आपने इसे कैसे किया? connectedCallback
में आपने this.attachShadow
कॉल किया था, जो किसी एलिमेंट में शैडो रूट जोड़ता है. open
मोड का मतलब है कि शैडो कॉन्टेंट की जांच की जा सकती है और शैडो रूट को this.shadowRoot
के ज़रिए भी ऐक्सेस किया जा सकता है. Chrome इंस्पेक्टर में वेब कॉम्पोनेंट पर भी एक नज़र डालें:
अब आपको एक ऐसा शैडो रूट दिखेगा जिसे बड़ा किया जा सकता है. इसमें कॉन्टेंट होता है. उस शैडो रूट के अंदर की हर चीज़ को शैडो DOM कहा जाता है. अगर आपको Chrome Dev टूल में रेटिंग एलिमेंट को चुनने और $0.children
को कॉल करने का विकल्प मिलता है, तो दिखेगा कि इससे कोई चिल्ड्रन नहीं दिखता. ऐसा इसलिए होता है, क्योंकि शैडो डीओएम को डायरेक्ट चिल्ड्रन वाले एक डीओएम ट्री का हिस्सा नहीं, बल्कि शैडो ट्री का हिस्सा माना जाता है.
लाइट डीओएम
प्रयोग: <rating-element>
के डायरेक्ट चाइल्ड के रूप में नोड जोड़ें:
index.html
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
पेज को रीफ़्रेश करने पर, आपको दिखेगा कि इस कस्टम एलिमेंट के लाइट डीओएम में यह नया डीओएम नोड पेज पर नहीं दिखता. ऐसा इसलिए होता है, क्योंकि शैडो डीओएम में यह कंट्रोल करने की सुविधाएं होती हैं कि <slot>
एलिमेंट के ज़रिए शैडो डॉम में लाइट डीओएम नोड को कैसे प्रोजेक्ट किया जाए.
5. HTML टेम्प्लेट
टेंप्लेट क्यों
innerHTML
और टेंप्लेट की लिटरल स्ट्रिंग का इस्तेमाल करने पर, स्क्रिप्ट इंजेक्शन के दौरान सुरक्षा से जुड़ी समस्याएं हो सकती हैं. इन लिटरल स्ट्रिंग को सैनिटेशन के बिना इस्तेमाल किया जाता है. पहले के तरीकों में, DocumentFragment
का इस्तेमाल किया गया था. हालांकि, इनमें दूसरी समस्याएं भी आ सकती हैं. जैसे, टेंप्लेट तय होने के दौरान इमेज लोड होना और स्क्रिप्ट का चलना और उन्हें फिर से इस्तेमाल करने में आने वाली रुकावटें. यहां <template>
एलिमेंट की ज़रूरत पड़ती है; टेंप्लेट, इनर्ट डीओएम देते हैं. यह नोड को क्लोन करने के लिए बेहतर परफ़ॉर्म करने वाला तरीका है और फिर से इस्तेमाल किए जा सकने वाले टेंप्लेट भी उपलब्ध कराता है.
टेंप्लेट का इस्तेमाल करना
इसके बाद, एचटीएमएल टेंप्लेट का इस्तेमाल करने के लिए कॉम्पोनेंट को ट्रांज़िशन करें:
index.html
<body>
<template id="rating-element-template">
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating"></span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
</template>
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
</body>
यहां आपने डीओएम कॉन्टेंट को मुख्य दस्तावेज़ के डीओएम में मौजूद टेंप्लेट टैग में मूव कर दिया है. अब कस्टम एलिमेंट की डेफ़िनिशन को रीफ़ैक्टर करें:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
const templateContent = document.getElementById('rating-element-template').content;
const clonedContent = templateContent.cloneNode(true);
shadowRoot.appendChild(clonedContent);
this.shadowRoot.querySelector('.rating').innerText = this.rating;
}
}
customElements.define('rating-element', RatingElement);
इस टेंप्लेट एलिमेंट का इस्तेमाल करने के लिए, आपको टेंप्लेट से क्वेरी करनी होती है और इसका कॉन्टेंट मिलता है. साथ ही, templateContent.cloneNode
की मदद से उन नोड का क्लोन बनाया जाता है जहां true
आर्ग्युमेंट डीप क्लोन करता है. इसके बाद, डेटा के साथ डॉम शुरू किया जाता है.
बधाई हो, अब आपके पास वेब कॉम्पोनेंट है! माफ़ करें, अभी इसमें कुछ करने की ज़रूरत नहीं है. इसलिए, कुछ सुविधाएं जोड़ें.
6. सुविधाएं जोड़ना
प्रॉपर्टी बाइंडिंग
फ़िलहाल, रेटिंग-एलिमेंट पर रेटिंग सेट करने का सिर्फ़ एक तरीका है. इसके लिए, एलिमेंट को बनाएं, ऑब्जेक्ट पर rating
प्रॉपर्टी सेट करें, और फिर उसे पेज पर रखें. माफ़ करें, नेटिव एचटीएमएल एलिमेंट के काम करने का तरीका आम तौर पर ऐसा नहीं होता. नेटिव एचटीएमएल एलिमेंट, प्रॉपर्टी और एट्रिब्यूट, दोनों में बदलाव होने पर अपडेट होते हैं.
rating
प्रॉपर्टी में बदलाव होने पर, कस्टम एलिमेंट को व्यू में अपडेट करने के लिए, ये लाइनें जोड़ें:
index.js
constructor() {
super();
this._rating = 0;
}
set rating(value) {
this._rating = value;
if (!this.shadowRoot) {
return;
}
const ratingEl = this.shadowRoot.querySelector('.rating');
if (ratingEl) {
ratingEl.innerText = this._rating;
}
}
get rating() {
return this._rating;
}
रेटिंग प्रॉपर्टी के लिए सेटर और गैटर जोड़ा जाता है. इसके बाद, अगर रेटिंग एलिमेंट का टेक्स्ट उपलब्ध है, तो उसे अपडेट कर दिया जाता है. इसका मतलब है कि अगर आपको एलिमेंट पर रेटिंग प्रॉपर्टी सेट करनी है, तो व्यू अपडेट हो जाएगा; अपने Dev टूल कंसोल में इसे तुरंत टेस्ट करें!
एट्रिब्यूट बाइंडिंग
अब, एट्रिब्यूट बदलने पर व्यू को अपडेट करें; यह, <input value="newValue">
सेट करने पर अपने व्यू को अपडेट करने वाले इनपुट जैसा है. अच्छी बात यह है कि वेब कॉम्पोनेंट के लाइफ़साइकल में attributeChangedCallback
शामिल होता है. रेटिंग अपडेट करने के लिए, ये लाइनें जोड़ें:
index.js
static get observedAttributes() {
return ['rating'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
}
}
attributeChangedCallback
को ट्रिगर करने के लिए, आपको RatingElement.observedAttributes which defines the attributes to be observed for changes
के लिए स्टैटिक गैटर सेट करना होगा. इसके बाद, डीओएम में रेटिंग को डिक्लेरेटिव तरीके से सेट किया जाता है. इसे आज़माएं:
index.html
<rating-element rating="5"></rating-element>
रेटिंग को अब एलान के तौर पर अपडेट किया जाना चाहिए!
बटन की सुविधा
सिर्फ़ बटन की सुविधा ही गायब है. इस कॉम्पोनेंट के व्यवहार से उपयोगकर्ता को एक अप या डाउन वोट की रेटिंग देने और उपयोगकर्ता को विज़ुअल सुझाव देने की सुविधा मिलनी चाहिए. इसे कुछ इवेंट लिसनर और बताने वाली प्रॉपर्टी के साथ लागू किया जा सकता है. हालांकि, विज़ुअल सुझाव देने के लिए पहले इन लाइनों को जोड़कर स्टाइल को अपडेट करें:
index.html
<style>
...
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
शैडो DOM में :host
सिलेक्टर उस नोड या कस्टम एलिमेंट के बारे में बताता है जिससे शैडो रूट जुड़ा है. ऐसे मामले में, अगर vote
एट्रिब्यूट "up"
है, तो थंब-अप बटन का रंग हरा हो जाएगा. हालांकि, अगर vote
एट्रिब्यूट की वैल्यू "down", then it will turn the thumb-down button red
है, तो इसका रंग हरा हो जाएगा. अब, इसके लिए लॉजिक लागू करें. इसके लिए, vote
के लिए भी वही प्रॉपर्टी / एट्रिब्यूट बनाएं जो आपने rating
को लागू करने के लिए लागू किया था. प्रॉपर्टी सेटर और गैटर से शुरू करें:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
}
get vote() {
return this._vote;
}
constructor
में, _vote
इंस्टेंस प्रॉपर्टी को null
से शुरू किया जाता है. साथ ही, सेटर में देखा जाता है कि नई वैल्यू अलग है या नहीं. अगर ऐसा है, तो आप उसके हिसाब से रेटिंग में बदलाव करें. साथ ही, this.setAttribute
की मदद से होस्ट को vote
एट्रिब्यूट की वैल्यू फिर से दिखाएं.
इसके बाद, एट्रिब्यूट बाइंडिंग सेट अप करें:
index.js
static get observedAttributes() {
return ['rating', 'vote'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
} else if (attributeName === 'vote') {
this.vote = newValue;
}
}
फिर से, यह वही प्रोसेस है जिसे आपने rating
एट्रिब्यूट बाइंडिंग से पूरा किया था; observedAttributes
में vote
जोड़ा जाता है और attributeChangedCallback
में vote
प्रॉपर्टी को सेट किया जाता है. अब, बटन से जुड़ी सुविधाएं देने के लिए, क्लिक इवेंट लिसनर जोड़ें!
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
this._boundOnUpClick = this._onUpClick.bind(this);
this._boundOnDownClick = this._onDownClick.bind(this);
}
connectedCallback() {
...
this.shadowRoot.querySelector('.thumb_up')
.addEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.addEventListener('click', this._boundOnDownClick);
}
disconnectedCallback() {
this.shadowRoot.querySelector('.thumb_up')
.removeEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.removeEventListener('click', this._boundOnDownClick);
}
_onUpClick() {
this.vote = 'up';
}
_onDownClick() {
this.vote = 'down';
}
constructor
में, कुछ क्लिक लिसनर को एलिमेंट से बाइंड किया जाता है और रेफ़रंस को आस-पास रखा जाता है. connectedCallback
में, बटन पर मौजूद क्लिक इवेंट को सुना जाता है. disconnectedCallback
में, इन लिसनर को हटाया जाता है और क्लिक लिसनर पर, आपने vote
को सही तरीके से सेट किया है.
बधाई हो, अब आपके पास सभी सुविधाओं वाला वेब कॉम्पोनेंट है; कुछ बटनों पर क्लिक करके देखें! अब समस्या यह है कि मेरी JS फ़ाइल 96 लाइन और मेरी एचटीएमएल फ़ाइल 43 लाइन तक पहुंच रही है. साथ ही, कोड बहुत ज़्यादा शब्दों में बताया गया है और इतने साधारण कॉम्पोनेंट के लिए ज़रूरी है. ऐसे में, Google के Lit प्रोजेक्ट की मदद ली जा सकती है!
7. लिट-एचटीएमएल
कोड चेकपॉइंट
lit-html क्यों
सबसे अहम बात यह है कि <template>
टैग काम का है और बेहतर परफ़ॉर्म करता है. हालांकि, इसे कॉम्पोनेंट के लॉजिक से पैकेज नहीं किया गया है. इस वजह से, बाकी के लॉजिक के साथ टेंप्लेट को बांटना मुश्किल हो जाता है. इसके अलावा, जिस तरह से टेंप्लेट एलिमेंट का इस्तेमाल किया जाता है उससे ज़रूरी कोड मिलता है. कई मामलों में, यह डिक्लेरेटिव कोडिंग पैटर्न की तुलना में, कम पढ़ने वाले कोड का इस्तेमाल करता है.
यहां lit-html की ज़रूरत पड़ती है! Lit html, Lit का रेंडरिंग सिस्टम है. इससे आपको JavaScript में एचटीएमएल टेंप्लेट लिखने और डीओएम बनाने और अपडेट करने के लिए, डेटा के साथ असरदार तरीके से उन टेंप्लेट को रेंडर और फिर से रेंडर करने की सुविधा मिलती है. यह लोकप्रिय JSX और VDOM लाइब्रेरी की तरह ही काम करता है. हालांकि, यह ब्राउज़र में नेटिव तौर पर काम करता है और कई मामलों में बेहतर तरीके से काम करता है.
लिट एचटीएमएल का इस्तेमाल करना
इसके बाद, नेटिव वेब कॉम्पोनेंट rating-element
को माइग्रेट करें, ताकि टैग किए गए टेंप्लेट का इस्तेमाल करने वाले लिट टेंप्लेट का इस्तेमाल किया जा सके. ये ऐसे फ़ंक्शन होते हैं जो खास सिंटैक्स वाले टेंप्लेट स्ट्रिंग को आर्ग्युमेंट के तौर पर लेते हैं. Lit उसके बाद, तेज़ी से रेंडर करने और सुरक्षा के लिए सैनिटाइज़ेशन की कुछ सुविधाएं देने के लिए, हुड के अंदर मौजूद टेंप्लेट एलिमेंट का इस्तेमाल करता है. वेबकॉम्पोनेंट में render()
तरीका जोड़कर, index.html
में मौजूद <template>
को Lit टेंप्लेट में माइग्रेट करके शुरुआत करें:
index.js
// Dont forget to import from Lit!
import {render, html} from 'lit';
class RatingElement extends HTMLElement {
...
render() {
if (!this.shadowRoot) {
return;
}
const template = html`
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
<button class="thumb_down">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
render(template, this.shadowRoot);
}
}
आपके पास index.html
से अपना टेंप्लेट मिटाने का विकल्प भी है. रेंडर करने के इस तरीके में, आपने template
नाम का एक वैरिएबल सेट किया है और html
टैग किए गए टेंप्लेट का लिटरल फ़ंक्शन शुरू किया है. आपको यह भी दिखेगा कि आपने ${...}
एलिमेंट के लिटरल इंटरपोलेशन सिंटैक्स का इस्तेमाल करके, span.rating
एलिमेंट में सामान्य डेटा बाइंडिंग का काम किया है. इसका मतलब है कि अब आपको उस नोड को अपडेट करने की ज़रूरत नहीं पड़ेगी. इसके अलावा, लिट render
तरीके को कॉल किया जाता है, जो टेंप्लेट को शैडो रूट में सिंक्रोनस रूप से रेंडर करता है.
डिक्लेरेटिव सिंटैक्स पर माइग्रेट करना
<template>
एलिमेंट को हटाने के बाद, अब तय किए गए render
तरीके को कॉल करने के लिए, कोड को रीफ़ैक्टर करें. लिसनर कोड को हटाने के लिए, lit की इवेंट लिसनर बाइंडिंग का इस्तेमाल करके शुरुआत की जा सकती है:
index.js
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
...
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
लिटिल टेंप्लेट, @EVENT_NAME बाइंडिंग सिंटैक्स वाले नोड में इवेंट लिसनर जोड़ सकते हैं. इस मामले में, जब भी इन बटन पर क्लिक किया जाता है, तब vote
प्रॉपर्टी को अपडेट किया जाता है.
इसके बाद, constructor
के साथ-साथ connectedCallback
और disconnectedCallback
से इवेंट लिसनर शुरू करने के कोड को हटाएं:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
connectedCallback() {
this.attachShadow({mode: 'open'});
this.render();
}
// remove disonnectedCallback and _onUpClick and _onDownClick
आपके पास सभी तीन कॉलबैक से, क्लिक लिसनर लॉजिक को हटाने के साथ-साथ disconnectedCallback
को पूरी तरह से हटाने का भी विकल्प है! आपने connectedCallback
से सभी डीओएम इनिशलाइज़ेशन कोड को हटा दिया है, जिससे यह ज़्यादा शानदार दिखता है. इसका मतलब यह भी है कि आपको _onUpClick
और _onDownClick
लिसनर के तरीकों से छुटकारा मिल सकता है!
आखिर में, render
तरीके का इस्तेमाल करने के लिए प्रॉपर्टी सेटर को अपडेट करें, ताकि प्रॉपर्टी या एट्रिब्यूट में बदलाव होने पर डोमेन अपडेट हो सके:
index.js
set rating(value) {
this._rating = value;
this.render();
}
...
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
// add render method
this.render();
}
यहां, आपने rating
सेटर से डॉम अपडेट लॉजिक हटाया और vote
सेटर से render
में कॉल जोड़ा. टेंप्लेट को अब आसानी से पढ़ा जा सकता है, क्योंकि अब यह देखा जा सकता है कि बाइंडिंग और इवेंट लिसनर कहां लागू होते हैं.
पेज रीफ़्रेश करें. इसके बाद, 'मुझे पसंद है' बटन दबाने पर रेटिंग देने वाला बटन ऐसा दिखना चाहिए!
8. LitElement
LitElement क्यों
कोड में अब भी कुछ समस्याएं हैं. सबसे पहले, अगर vote
प्रॉपर्टी या एट्रिब्यूट को बदला जाता है, तो इससे rating
प्रॉपर्टी बदल सकती है. इसकी वजह से, render
को दो बार कॉल किया जाएगा. रेंडर करने के बार-बार इस्तेमाल किए जाने के बावजूद, JavaScript वीएम अब भी उस फ़ंक्शन को सिंक्रोनस रूप से दो बार कॉल करने में समय बिता रहा है. दूसरी वजह, नई प्रॉपर्टी और एट्रिब्यूट जोड़ना मुश्किल लगता है, क्योंकि इसके लिए बहुत सारे बॉयलरप्लेट कोड की ज़रूरत पड़ती है. ऐसी ही स्थिति में LitElement
की ज़रूरत पड़ती है!
LitElement
, Lit की बेस क्लास की तरह है. यह तेज़ी से काम करने वाले ऐसे वेब कॉम्पोनेंट बनाता है जो कम वज़न वाले हैं और इनका इस्तेमाल फ़्रेमवर्क और एनवायरमेंट में किया जा सकता है. इसके बाद, देखें कि LitElement
, लागू करने के तरीके में बदलाव करके rating-element
में हमारे लिए क्या-क्या कर सकता है!
LitElement का इस्तेमाल करना
lit
पैकेज से, LitElement
बेस क्लास को इंपोर्ट और सब-क्लास करके शुरू करें:
index.js
import {LitElement, html, css} from 'lit';
class RatingElement extends LitElement {
// remove connectedCallback()
...
आपने LitElement
को इंपोर्ट किया है, जो rating-element
का नया बेस क्लास है. अब आप html
को इंपोर्ट करते रहेंगे और आखिर में css
. इसकी मदद से, हम सीएसएस की गणित, टेंप्लेट बनाने, और अन्य सुविधाओं के लिए, सीएसएस टैग किए गए टेंप्लेट की लिटरल वैल्यू तय कर पाएंगे.
इसके बाद, स्टाइल को रेंडर करने के तरीके से Lit की स्टैटिक स्टाइलशीट पर ले जाएं:
index.js
class RatingElement extends LitElement {
static get styles() {
return css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
`;
}
...
लिटरेचर में ज़्यादातर स्टाइल यहां मौजूद हैं. लीट इन स्टाइल को अपनाएगा और कंस्ट्रक्शनेबल स्टाइलशीट जैसी ब्राउज़र की सुविधाओं का इस्तेमाल करेगा, ताकि रेंडरिंग समय को कम किया जा सके. साथ ही, ज़रूरत पड़ने पर इसे पुराने ब्राउज़र पर वेब कॉम्पोनेंट पॉलीफ़िल के ज़रिए पास किया जा सके.
लाइफ़साइकल
Lit, नेटिव वेब कॉम्पोनेंट कॉलबैक के ऊपर, रेंडर लाइफ़साइकल कॉलबैक मैथड का एक सेट पेश करता है. ये कॉलबैक तब ट्रिगर होते हैं, जब तय की गई Lit प्रॉपर्टी को बदला जाता है.
इस सुविधा का इस्तेमाल करने के लिए, आपको स्टैटिक तरीके से एलान करना होगा कि कौनसी प्रॉपर्टी रेंडर की लाइफ़साइकल को ट्रिगर करेगी.
index.js
static get properties() {
return {
rating: {
type: Number,
},
vote: {
type: String,
reflect: true,
}
};
}
// remove observedAttributes() and attributeChangedCallback()
// remove set rating() get rating()
यहां, यह बताया जाता है कि rating
और vote
, LitElement रेंडरिंग लाइफ़साइकल ट्रिगर करेंगे. साथ ही, यह भी तय करेंगे कि किस टाइप का इस्तेमाल, स्ट्रिंग एट्रिब्यूट को प्रॉपर्टी में बदलने के लिए किया जाएगा.
<user-profile .name=${this.user.name} .age=${this.user.age}>
${this.user.family.map(member => html`
<family-member
.name=${member.name}
.relation=${member.relation}>
</family-member>`)}
</user-profile>
इसके अलावा, vote
प्रॉपर्टी पर मौजूद reflect
फ़्लैग, होस्ट एलिमेंट के vote
एट्रिब्यूट को अपने-आप अपडेट कर देगा, जिसे आपने vote
सेटर में मैन्युअल तरीके से ट्रिगर किया था.
अब आपके पास स्टैटिक प्रॉपर्टी ब्लॉक मौजूद है, तो अपडेट होने वाले लॉजिक को रेंडर करने वाले सभी एट्रिब्यूट और प्रॉपर्टी को हटाया जा सकता है. इसका मतलब है कि इन तरीकों को हटाया जा सकता है:
connectedCallback
observedAttributes
attributeChangedCallback
rating
(सेटर और गैटर)vote
(सेटर और गेटर, लेकिन सेटर से बदलाव वाला लॉजिक बनाए रखें)
आप सिर्फ़ constructor
को बनाए रखते हैं और willUpdate
लाइफ़साइकल का नया तरीका जोड़ रहे हैं:
index.js
constructor() {
super();
this.rating = 0;
this.vote = null;
}
willUpdate(changedProps) {
if (changedProps.has('vote')) {
const newValue = this.vote;
const oldValue = changedProps.get('vote');
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
}
}
// remove set vote() and get vote()
यहां, rating
और vote
को शुरू किया जाता है और vote
सेटर लॉजिक को willUpdate
लाइफ़साइकल तरीके पर ले जाया जाता है. जब भी अपडेट की जा रही कोई प्रॉपर्टी बदली जाती है, तो willUpdate
तरीके को render
से पहले कॉल किया जाता है. ऐसा इसलिए होता है, क्योंकि LitElement बैच प्रॉपर्टी में बदलाव होता है और वह एसिंक्रोनस रेंडरिंग होती है. willUpdate
की रिऐक्टिव प्रॉपर्टी (जैसे कि this.rating
) में बदलाव करने से, ग़ैर-ज़रूरी render
लाइफ़साइकल कॉल ट्रिगर नहीं होंगे.
आखिर में, render
एक LitElement लाइफ़साइकल तरीका है, जिसके लिए हमें Lit टेंप्लेट लौटाना है:
index.js
render() {
return html`
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
}
अब आपको शैडो रूट की जांच करने की ज़रूरत नहीं है और अब आपको 'lit'
पैकेज से इंपोर्ट किए गए render
फ़ंक्शन को कॉल करने की ज़रूरत नहीं है.
आपका एलिमेंट अब झलक में रेंडर होना चाहिए; इस पर क्लिक करें!
9. बधाई हो
बधाई हो, आपने शुरुआत से वेब कॉम्पोनेंट बना लिया है और उसे LitElement में बदल दिया है!
Lit बहुत छोटा है (< 5kb minified + gzip), बहुत तेज़ है, और कोड करने में बहुत मज़ेदार है! दूसरे फ़्रेमवर्क में इस्तेमाल किए जा सकने वाले कॉम्पोनेंट बनाए जा सकते हैं या इनकी मदद से सभी तरह के ऐप्लिकेशन बनाए जा सकते हैं!
अब आपको पता है कि वेब कॉम्पोनेंट क्या होता है, उसे कैसे बनाया जाता है, और Lit ने उन्हें कैसे आसानी से बनाया है!
कोड चेकपॉइंट
क्या आपको हमारे कोड के हिसाब से, अपने फ़ाइनल कोड की जांच करनी है? इसकी तुलना यहां करें.
आगे क्या होगा?
कुछ अन्य कोडलैब देखें!
- Lit for React Developers
- लिट-एलिमेंट की मदद से ब्रिक व्यूअर बनाएं
- लिट-एलिमेंट की मदद से स्टोरी कॉम्पोनेंट बनाना
आगे पढ़ें
- इंटरैक्टिव ट्यूटोरियल पढ़ें
- लिट दस्तावेज़ों
- ओपन वेब कॉम्पोनेंट - यह कम्यूनिटी दिशा-निर्देश और टूलिंग कम्यूनिटी का इस्तेमाल करती है
- WebComponents.dev - सभी जाने-पहचाने फ़्रेमवर्क में वेब कॉम्पोनेंट बनाएं
कम्यूनिटी
- Lit and Friends Slack - वेब कॉम्पोनेंट की सबसे बड़ी कम्यूनिटी
- @buildWithLit पर Twitter - उस टीम का Twitter खाता जिसने Lit को बनाया
- वेब कॉम्पोनेंट SF - सैन फ़्रांसिस्को के लिए एक वेब कॉम्पोनेंट सम्मेलन