टेंप्लेट, स्लॉट, और शैडो

वेब कॉम्पोनेंट को दोबारा इस्तेमाल करने से यह फ़ायदा होता है: यूज़र इंटरफ़ेस (यूआई) विजेट एक बार बनाया जा सकता है और फिर उसका कई बार इस्तेमाल किया जा सकता है. हालांकि, वेब कॉम्पोनेंट बनाने के लिए JavaScript की ज़रूरत नहीं होती, तो आपको JavaScript लाइब्रेरी की ज़रूरत नहीं होती. एचटीएमएल और उससे जुड़े एपीआई आपकी ज़रूरत की हर चीज़ देते हैं.

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

इस सेक्शन में, हम <star-rating> एलिमेंट बनाएंगे. यह एक ऐसा वेब कॉम्पोनेंट है जो लोगों को का पैमाना एक से पांच स्टार तक होना चाहिए. किसी कस्टम एलिमेंट को नाम देते समय, हमारा सुझाव है कि आप अंग्रेज़ी के सभी छोटे अक्षरों का इस्तेमाल करें. साथ ही, डैश शामिल करें, इसकी मदद से, सामान्य और कस्टम एलिमेंट के बीच अंतर किया जा सकता है.

हम टेंप्लेट बनाने के लिए, <template> और <slot> एलिमेंट, slot एट्रिब्यूट, और JavaScript का इस्तेमाल करने पर चर्चा करेंगे इनकैप्सुलेट किया गया शैडो DOM. इसके बाद हम टेक्स्ट के सेक्शन को पसंद के मुताबिक बनाते हुए, तय किए गए एलिमेंट का फिर से इस्तेमाल करेंगे. की तरह ही काम करेगा. हम कस्टम एलिमेंट में और उसके बाहर, सीएसएस का इस्तेमाल करने के बारे में भी कम शब्दों में चर्चा करेंगे.

<template> एलिमेंट

<template> एलिमेंट का इस्तेमाल, एचटीएमएल के उन फ़्रैगमेंट के बारे में बताने के लिए किया जाता है जिन्हें क्लोन किया जाना है और JavaScript की मदद से डीओएम में डाला जाना है. एलिमेंट का कॉन्टेंट, डिफ़ॉल्ट रूप से रेंडर नहीं होता है. इसके बजाय, उन्हें JavaScript का इस्तेमाल करके इंस्टैंशिएट किया जाता है.

<template id="star-rating-template">
  <form>
    <fieldset>
      <legend>Rate your experience:</legend>
      <rating>
        <input type="radio" name="rating" value="1" aria-label="1 star" required />
        <input type="radio" name="rating" value="2" aria-label="2 stars" />
        <input type="radio" name="rating" value="3" aria-label="3 stars" />
        <input type="radio" name="rating" value="4" aria-label="4 stars" />
        <input type="radio" name="rating" value="5" aria-label="5 stars" />
      </rating>
    </fieldset>
    <button type="reset">Reset</button>
    <button type="submit">Submit</button>
  </form>
</template>

<template> एलिमेंट का कॉन्टेंट, स्क्रीन पर नहीं लिखा जाता, इसलिए <form> और उसकी सामग्री को रेंडर नहीं किया जाता है. हां, यह कोडपेन खाली है, लेकिन अगर एचटीएमएल टैब की जांच की जाती है, तो आपको <template> मार्कअप दिखेगा.

इस उदाहरण में, <form>, डीओएम में मौजूद <template> का चाइल्ड नहीं है. इसके बजाय, <template> एलिमेंट का कॉन्टेंट चाइल्ड है HTMLTemplateElement.content से वापस की गई, कुल DocumentFragment में से प्रॉपर्टी. कॉन्टेंट दिखने के लिए JavaScript का इस्तेमाल करना ज़रूरी है, ताकि कॉन्टेंट इकट्ठा करके उसे डीओएम में जोड़ा जा सके.

इस छोटे JavaScript ने कस्टम एलिमेंट नहीं बनाया. इसके बजाय, इस उदाहरण ने <template> की सामग्री को <body> में जोड़ दिया है. कॉन्टेंट, दिखने वाले और स्टाइल वाले डीओएम का हिस्सा बन गया है.

पिछले कोडपेन का स्क्रीनशॉट, जैसा कि डीओएम में दिखाया गया है.

सिर्फ़ एक स्टार रेटिंग के लिए टेंप्लेट लागू करने के लिए JavaScript की ज़रूरत नहीं होती. हालांकि, इसकी मदद से वेब कॉम्पोनेंट को का बार-बार इस्तेमाल किया जा सकने वाला स्टार रेटिंग विजेट, पसंद के मुताबिक बनाया जा सकता है.

<slot> एलिमेंट

हम हर बार होने वाले इवेंट के लिए, पसंद के मुताबिक बनाए गए लेजेंड को शामिल करने के लिए एक स्लॉट शामिल करते हैं. एचटीएमएल <slot> उपलब्ध कराता है एलिमेंट को प्लेसहोल्डर के तौर पर <template> में प्लेसहोल्डर के तौर पर इस्तेमाल करता है, जो नाम दिए जाने पर "नाम वाला स्लॉट" बनाता है. नाम वाले स्लॉट का इस्तेमाल किया जा सकता है का इस्तेमाल करके, वेब कॉम्पोनेंट में कॉन्टेंट को पसंद के मुताबिक बनाया जा सकता है. <slot> एलिमेंट की मदद से, हम यह कंट्रोल कर पाते हैं कि कस्टम एलिमेंट को शैडो ट्री में डाला जाना चाहिए.

अपने टेंप्लेट में, हम <legend> को <slot> में बदल देते हैं:

<template id="star-rating-template">
  <form>
    <fieldset>
      <slot name="star-rating-legend">
        <legend>Rate your experience:</legend>
      </slot>

अगर एलिमेंट में कोई स्लॉट एट्रिब्यूट है और उसकी वैल्यू इससे मेल खाती है, तो name एट्रिब्यूट का इस्तेमाल, दूसरे एलिमेंट को स्लॉट असाइन करने के लिए किया जाता है नाम वाले स्लॉट का नाम. अगर कस्टम एलिमेंट में स्लॉट के लिए मैच नहीं है, तो <slot> का कॉन्टेंट रेंडर किया जाएगा. इसलिए, हमने सामान्य कॉन्टेंट के साथ एक <legend> शामिल किया है. अगर कोई व्यक्ति अपने एचटीएमएल में बिना किसी कॉन्टेंट के <star-rating></star-rating> को शामिल करता है, तो इसे रेंडर किया जा सकता है.

<star-rating>
  <legend slot="star-rating-legend">Blendan Smooth</legend>
</star-rating>
<star-rating>
  <legend slot="star-rating-legend">Hoover Sukhdeep</legend>
</star-rating>
<star-rating>
  <legend slot="star-rating-legend">Toasty McToastface</legend>
  <p>Is this text visible?</p>
</star-rating>

स्लॉट एट्रिब्यूट एक ग्लोबल एट्रिब्यूट है, जिसका इस्तेमाल किया जाता है <template> में <slot> की सामग्री बदलने के लिए. हमारे कस्टम एलिमेंट में, स्लॉट एट्रिब्यूट वाला एलिमेंट एक <legend> है. ज़रूरी नहीं है. हमारे टेंप्लेट में, <slot name="star-rating-legend"> को <anyElement slot="star-rating-legend"> से बदल दिया जाएगा, जहां <anyElement> कोई भी एलिमेंट हो सकता है, यहां तक कि कोई दूसरा कस्टम एलिमेंट भी.

ऐसे एलिमेंट जिनके बारे में जानकारी नहीं है

अपने <template> में हमने <rating> एलिमेंट का इस्तेमाल किया है. यह कस्टम एलिमेंट नहीं है. इसके बजाय, यह एक अनजान एलिमेंट है. ब्राउज़र नहीं होने दें, जो किसी एलिमेंट की पहचान नहीं करते. न पहचाने गए एचटीएमएल एलिमेंट को ब्राउज़र, बिना पहचान वाले इनलाइन के तौर पर देखता है एलिमेंट जिन्हें सीएसएस की मदद से स्टाइल किया जा सकता है. <span> की तरह, <rating> और <star-rating> एलिमेंट में कोई उपयोगकर्ता-एजेंट लागू नहीं किया गया है स्टाइल या सिमेंटिक्स.

ध्यान दें कि <template> और कॉन्टेंट को रेंडर नहीं किया गया है. <template> एक जाना-पहचाना एलिमेंट है, जिसमें ऐसा कॉन्टेंट होता है जो उसे रेंडर नहीं किया जाना है. <star-rating> एलिमेंट को अभी तय नहीं किया गया है. जब तक हम किसी एलिमेंट को तय नहीं करते, तब तक ब्राउज़र उसे दिखाता है की तरह हैं. फ़िलहाल, पहचान में न आने वाले <star-rating> को पहचान छिपाने वाला इनलाइन एलिमेंट माना जाता है. इसलिए, कॉन्टेंट इसमें लेजेंड और तीसरे <star-rating> में <p> शामिल होते हैं. इनके बजाय, वे ठीक वैसे ही दिखते हैं जैसे वे <span> में होते.

आइए, हमारे एलिमेंट को तय करते हैं, ताकि हम उस एलिमेंट को कस्टम एलिमेंट में बदल सकें.

कस्टम एलिमेंट

कस्टम एलिमेंट तय करने के लिए JavaScript ज़रूरी है. तय होने पर, <star-rating> एलिमेंट का कॉन्टेंट, शैडो रूट में उस टेंप्लेट का पूरा कॉन्टेंट शामिल होता है जिसे हम उससे जोड़ते हैं. टेंप्लेट के <slot> एलिमेंट को बदल दिया गया है <star-rating> में मौजूद उस एलिमेंट का कॉन्टेंट इस्तेमाल करें जिसके slot एट्रिब्यूट की वैल्यू, <slot> के नाम की वैल्यू से मेल खाती है. ऐसा तब होगा, जब एक है. अगर नहीं, तो टेंप्लेट के स्लॉट का कॉन्टेंट दिखाया जाता है.

कस्टम एलिमेंट में मौजूद ऐसा कॉन्टेंट जो किसी स्लॉट से नहीं जुड़ा है. जैसे, हमारे तीसरे <star-rating> में मौजूद <p>Is this text visible?</p>, इसमें शामिल नहीं है इसलिए बनाया नहीं गया है.

हम star-rating नाम का कस्टम एलिमेंट तय करते हैं HTMLElement को बढ़ाकर:

customElements.define('star-rating',
  class extends HTMLElement {
    constructor() {
      super(); // Always call super first in constructor
      const starRating = document.getElementById('star-rating-template').content;
      const shadowRoot = this.attachShadow({
        mode: 'open'
      });
      shadowRoot.appendChild(starRating.cloneNode(true));
    }
  });

एलिमेंट तय होने के बाद, जब भी ब्राउज़र को <star-rating> एलिमेंट मिलता है, तो उसे तय किए गए तरीके से रेंडर किया जाता है #star-rating-template वाले एलिमेंट से जोड़ा जा सकता है, जो हमारा टेंप्लेट है. ब्राउज़र, नोड में शैडो डीओएम ट्री को जोड़ेगा और उस शैडो डीओएम में टेंप्लेट के कॉन्टेंट का क्लोन. ध्यान दें कि जिन एलिमेंट पर attachShadow() का इस्तेमाल किया जा सकता है वे सीमित हैं.

const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(starRating.cloneNode(true));

अगर आप डेवलपर टूल पर एक नज़र डालें, तो आपको पता चलेगा कि <template> का <form>, हर कस्टम एलिमेंट के शैडो रूट का हिस्सा है. <template> के कॉन्टेंट का क्लोन, डेवलपर टूल के हर कस्टम एलिमेंट में दिखता है और ब्राउज़र में दिखता है. हालांकि, इसके कॉन्टेंट का क्लोन कस्टम एलिमेंट को स्क्रीन पर रेंडर नहीं किया जाता है.

DevTools का स्क्रीनशॉट, जिसमें हर कस्टम एलिमेंट में क्लोन किए गए टेंप्लेट का कॉन्टेंट दिखाया गया है.

<template> के उदाहरण में, हमने टेंप्लेट के कॉन्टेंट को दस्तावेज़ के मुख्य हिस्से में जोड़ दिया है. साथ ही, कॉन्टेंट को सामान्य डीओएम में जोड़ दिया है. customElements की परिभाषा में, हमने इसका इस्तेमाल किया है appendChild(), लेकिन क्लोन किए गए टेंप्लेट का कॉन्टेंट पूरी जानकारी वाला शैडो डीओएम.

क्या आपने देखा कि तारे फिर से बिना स्टाइल वाले रेडियो बटन में बदल गए? स्टैंडर्ड डीओएम के बजाय शैडो डीओएम का हिस्सा होने पर, कोडपेन के सीएसएस टैब में दी गई स्टाइल लागू नहीं होती. उस टैब की सीएसएस स्टाइल, शैडो डीओएम के बजाय दस्तावेज़ के हिसाब से तय किए जाते हैं. इसलिए, स्टाइल लागू नहीं होते. हमें एनकैप्सुलेटेड बनाना होगा स्टाइल के हिसाब से बनाया जा सकता है.

शैडो डीओएम

शैडो डीओएम, हर शैडो ट्री के सीएसएस स्टाइल को स्कोप करता है और उसे दस्तावेज़ के बाकी हिस्सों से अलग करता है. इसका मतलब है कि बाहरी सीएसएस आपके कॉम्पोनेंट पर लागू नहीं होता. साथ ही, कॉम्पोनेंट स्टाइल का दस्तावेज़ के बाकी हिस्से पर तब तक कोई असर नहीं पड़ता, जब तक हम जान-बूझकर उन्हें वहां ले जाएगा.

हमने शैडो डीओएम में कॉन्टेंट जोड़ दिया है, इसलिए हम <style> एलिमेंट शामिल कर सकते हैं कस्टम एलिमेंट के लिए, इनकैप्सुलेट की गई सीएसएस (सीएसएस) उपलब्ध कराना.

कस्टम एलिमेंट का दायरा होने पर, हमें दस्तावेज़ के बाकी हिस्से में स्टाइल के बारे में चिंता करने की ज़रूरत नहीं है. हम यह कर सकते हैं: चुनने वालों की विशेषता को काफ़ी हद तक कम कर सकता है. उदाहरण के लिए, कस्टम एलिमेंट में सिर्फ़ रेडियो इनपुट इस्तेमाल किए जाते हैं बटन के लिए, हम सिलेक्टर के रूप में input[type="radio"] के बजाय input का इस्तेमाल कर सकते हैं.

 <template id="star-rating-template">
  <style>
    rating {
      display: inline-flex;
    }
    input {
      appearance: none;
      margin: 0;
      box-shadow: none;
    }
    input::after {
      content: '\2605'; /* solid star */
      font-size: 32px;
    }
    rating:hover input:invalid::after,
    rating:focus-within input:invalid::after {
      color: #888;
    }
    input:invalid::after,
      rating:hover input:hover ~ input:invalid::after,
      input:focus ~ input:invalid::after  {
      color: #ddd;
    }
    input:valid {
      color: orange;
    }
    input:checked ~ input:not(:checked)::after {
      color: #ccc;
      content: '\2606'; /* hollow star */
    }
  </style>
  <form>
    <fieldset>
      <slot name="star-rating-legend">
        <legend>Rate your experience:</legend>
      </slot>
      <rating>
        <input type="radio" name="rating" value="1" aria-label="1 star" required/>
        <input type="radio" name="rating" value="2" aria-label="2 stars"/>
        <input type="radio" name="rating" value="3" aria-label="3 stars"/>
        <input type="radio" name="rating" value="4" aria-label="4 stars"/>
        <input type="radio" name="rating" value="5" aria-label="5 stars"/>
      </rating>
    </fieldset>
    <button type="reset">Reset</button>
    <button type="submit">Submit</button>
  </form>
</template>

हालांकि, वेब कॉम्पोनेंट को इन-<template> मार्कअप और सीएसएस स्टाइल के साथ इनकैप्सुलेट किया जाता है. साथ ही, इन्हें शैडो डीओएम और छिपाया गया है कॉम्पोनेंट के बाहर मौजूद सभी चीज़ों से, रेंडर होने वाला स्लॉट कॉन्टेंट, <anyElement slot="star-rating-legend"> <star-rating> के हिस्से को एनकैप्सुलेट नहीं किया गया है.

मौजूदा स्कोप के बाहर स्टाइल करना

शैडो डीओएम के अंदर से दस्तावेज़ को स्टाइल करना और शैडो डीओएम के कॉन्टेंट की स्टाइल करना मुमकिन है. हालांकि, यह आसान नहीं है ग्लोबल स्टाइल. शैडो बाउंड्री को पार करने के लिए, शैडो डीओएम खत्म होता है और सामान्य डीओएम शुरू होता है और जान-बूझकर किए गए हैं.

शैडो ट्री, शैडो DOM में मौजूद DOM ट्री होता है. शैडो रूट, शैडो ट्री का रूट नोड होता है.

:host pseudo-class, शैडो होस्ट एलिमेंट, <star-rating> को चुनता है. शैडो होस्ट वह DOM नोड होता है जिससे शैडो DOM जुड़ा होता है. होस्ट के सिर्फ़ कुछ वर्शन को टारगेट करने के लिए, :host() का इस्तेमाल करें. इससे सिर्फ़ वे शैडो होस्ट एलिमेंट चुने जाएंगे जो पास किए गए पैरामीटर से मैच होते हैं. जैसे, क्लास या एट्रिब्यूट चुनने वाला. चुनने के लिए कस्टम एलिमेंट बनाने से पहले, ग्लोबल सीएसएस में star-rating { /* styles */ } या टेंप्लेट स्टाइल में :host(:not(#nonExistantId)) का इस्तेमाल किया जा सकता है. शर्तों में खासियत के आधार पर, ग्लोबल सीएसएस जीतती है.

::slotted() सूडो-एलिमेंट, शैडो डीओएम सीमा को पार करता है शैडो DOM में. यह स्लॉट किए गए एलिमेंट को तब चुनता है, जब वह सिलेक्टर से मेल खाता है. हमारे उदाहरण में, ::slotted(legend) हमारे तीन लेजेंड से मेल खाता है.

ग्लोबल स्कोप में सीएसएस से शैडो डीओएम को टारगेट करने के लिए, टेंप्लेट में बदलाव करना होगा. part विशेषता को ऐसे किसी भी एलीमेंट में जोड़ा जा सकता है, जिसे आप शैली देना चाहते हैं. इसके बाद, ::part() स्यूडो-एलिमेंट का इस्तेमाल करें शैडो ट्री में मौजूद उन एलिमेंट को मैच करने की सुविधा देता है जो पास किए गए पैरामीटर से मैच होते हैं. स्यूडो-एलिमेंट के लिए ऐंकर या ओरिजनल एलिमेंट है होस्ट या कस्टम एलिमेंट का नाम, इस मामले में star-rating. पैरामीटर, part एट्रिब्यूट की वैल्यू होता है.

अगर हमारे टेंप्लेट का मार्कअप इस तरह शुरू हुआ हो:

<template id="star-rating-template">
  <form part="formPart">
    <fieldset part="fieldsetPart">

हम <form> और <fieldset> को इनसे टारगेट कर सकते हैं:

star-rating::part(formPart) { /* styles */ }
star-rating::part(fieldsetPart) { /* styles */ }

पार्ट के नाम, क्लास की तरह काम करते हैं: किसी एलिमेंट में स्पेस से अलग किए गए कई पार्ट नाम हो सकते हैं, और एक से ज़्यादा एलिमेंट ये कर सकते हैं पार्ट का नाम एक जैसा है.

Google के पास कस्टम एलिमेंट बनाने के लिए शानदार चेकलिस्ट हैं. शायद आप यह भी जानना चाहें कि डिक्लेरेटिव शैडो DOM के बारे में.

देखें कि आपको कितना समझ आया है

टेंप्लेट, स्लॉट, और शैडो के बारे में अपनी जानकारी परखें.

डिफ़ॉल्ट रूप से शैडो डीओएम के बाहर के स्टाइल, एलिमेंट को स्टाइल करेंगे.

सही.
फिर से कोशिश करें.
गलत.
सही!

इनमें से कौनसा जवाब <template> एलिमेंट की सही जानकारी है?

एक सामान्य एलिमेंट, जिसका इस्तेमाल आपके पेज पर किसी भी कॉन्टेंट को दिखाने के लिए किया जाता है.
फिर से कोशिश करें.
कोई प्लेसहोल्डर एलिमेंट.
फिर से कोशिश करें.
एचटीएमएल के फ़्रैगमेंट के बारे में बताने के लिए इस्तेमाल किया जाने वाला एलिमेंट, जिसे डिफ़ॉल्ट रूप से रेंडर नहीं किया जाएगा.
सही!