Shadow DOM v1 - सेल्फ़-कंटेन्ड वेब कॉम्पोनेंट

शैडो डीओएम की मदद से वेब डेवलपर, वेब कॉम्पोनेंट के लिए छोटे-छोटे डीओएम और सीएसएस बना सकते हैं

खास जानकारी

शैडो डीओएम, वेब ऐप्लिकेशन बनाने में आने वाली आसानी को हटा देता है. भंवरपन यह एचटीएमएल, सीएसएस, और JS की ग्लोबल प्रकृति से मिलता है. पिछले कुछ सालों में हमने देखा है कि बहुत ज़्यादा संख्या का आविष्कार किया में से टूल समस्याओं से बचने के लिए ज़रूरी कदम उठाएँ. उदाहरण के लिए, नए एचटीएमएल आईडी/क्लास का इस्तेमाल करने पर, इसका कोई असर नहीं है कि पेज के लिए पहले से इस्तेमाल किए जा रहे किसी नाम से इस नाम का विरोध होगा या नहीं. छिपे हुए छोटे-छोटे बग, सीएसएस की खासियत एक बड़ी समस्या बन जाती है (सब कुछ !important!), स्टाइल चुनने वालों का कंट्रोल खत्म हो जाता है और परफ़ॉर्मेंस पर असर पड़ सकता है. सूची चलता रहता है.

शैडो DOM से सीएसएस और DOM को ठीक किया जाता है. यह वेब पर स्कोप वाली स्टाइल के बारे में जानकारी देता है प्लैटफ़ॉर्म. टूल या नामकरण कन्वेंशन के बिना, आप सीएसएस को मार्कअप, लागू करने की जानकारी छिपाएं, और लेखक के बारे में पूरी जानकारी कॉम्पोनेंट, वैनिला JavaScript में शामिल हैं.

परिचय

शैडो डीओएम, वेब कॉम्पोनेंट के तीन स्टैंडर्ड में से एक है: एचटीएमएल टेंप्लेट, शैडो डीओएम और कस्टम एलिमेंट. एचटीएमएल इंपोर्ट पहले इस सूची का हिस्सा था, लेकिन अब इसे अब सेवा में नहीं है.

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

शैडो DOM को कॉम्पोनेंट-आधारित ऐप्लिकेशन बनाने के लिए एक टूल के रूप में डिज़ाइन किया गया है. इसलिए, यह वेब डेवलपमेंट की आम समस्याओं के समाधान उपलब्ध कराता है:

  • अलग-अलग डीओएम: कॉम्पोनेंट का डीओएम अपने-आप शामिल होता है (उदाहरण के लिए, document.querySelector(), कॉम्पोनेंट के शैडो डीओएम में नोड नहीं दिखाएगा.
  • स्कोप किया गया सीएसएस: शैडो डीओएम में तय किया गया सीएसएस, इसके दायरे में आता है. स्टाइल के नियम लीक न हो सकें और पेज स्टाइल खुल न जाएं.
  • कंपोज़िशन: अपने कॉम्पोनेंट के लिए, मार्कअप पर आधारित एपीआई डिज़ाइन करें.
  • सीएसएस को आसान बनाता है - स्कोप वाले डीओएम का मतलब है कि सीएसएस सिलेक्टर का इस्तेमाल किया जा सकता है. इसके अलावा, और भी बहुत कुछ किया जा सकता है और नाम रखने के विरोधों की चिंता न करें.
  • प्रोडक्टिविटी - ऐप्लिकेशन को एक बड़े ऐप्लिकेशन के बजाय डीओएम के अलग-अलग हिस्सों में बांटें (ग्लोबल) पेज पर जाएं.

fancy-tabs का डेमो

इस पूरे लेख में, हम डेमो कॉम्पोनेंट (<fancy-tabs>) के बारे में बताएंगे और इससे कोड स्निपेट का रेफ़रंस देकर. अगर आपके ब्राउज़र पर एपीआई की सुविधा काम करती है, तो आपको नीचे इसका लाइव डेमो दिखेगा. अगर ऐसा नहीं है, तो GitHub पर पूरा सोर्स देखें.

GitHub पर सोर्स देखें

शैडो डीओएम क्या है?

DOM पर बैकग्राउंड

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

जब ब्राउज़र किसी वेब पेज को लोड करता है, तब यह कई दिलचस्प चीज़ें करता है. इनमें से एक और भी कई काम करता है. वह लेखक के एचटीएमएल को लाइव दस्तावेज़ में बदल देता है. बुनियादी रूप से, पेज के स्ट्रक्चर को समझने के लिए ब्राउज़र, एचटीएमएल (स्टैटिक स्ट्रिंग) को डेटा मॉडल (ऑब्जेक्ट/नोड) में शामिल करना. ब्राउज़र सुरक्षित रखता है एचटीएमएल की हैरारकी है, जिसमें इन नोड का ट्री बनाया जाता है: DOM. मज़ेदार बात DOM के बारे में बताती है कि यह आपके पेज का लाइव प्रतिनिधित्व है. स्टैटिक से अलग एचटीएमएल जिसे हम लिखते हैं, ब्राउज़र के ज़रिए बनाए गए नोड में प्रॉपर्टी, मेथड, और सबसे बेहतर सभी... प्रोग्राम से छेड़छाड़ की जा सकती है! इसलिए, हम डीओएम बना सकते हैं एलिमेंट, जो सीधे JavaScript का इस्तेमाल करते हैं:

const header = document.createElement('header');
const h1 = document.createElement('h1');
h1.textContent = 'Hello DOM';
header.appendChild(h1);
document.body.appendChild(header);

यह एचटीएमएल मार्कअप बनाता है:

<body>
    <header>
    <h1>Hello DOM</h1>
    </header>
</body>

यह सब बढ़िया है. इसके बाद शैडो डीओएम क्या है?

शैडो में DOM...

शैडो डीओएम दो अंतर वाला सामान्य डीओएम है: 1) उसे बनाने/इस्तेमाल करने का तरीका और 2) पेज के बाकी हिस्से के मुकाबले इसका व्यवहार कैसा होता है. आम तौर पर, डीओएम बनाया जाता है नोड और उन्हें किसी दूसरे एलिमेंट के चिल्ड्रेन के रूप में जोड़ सकते हैं. शैडो डीओएम की मदद से, आपको एक स्कोप वाला डीओएम ट्री बनाएं, जो एलिमेंट से जुड़ा हो, लेकिन असल बच्चे. इस स्कोप वाले सबट्री को शैडो ट्री कहा जाता है. एलिमेंट यह इसके शैडो होस्ट से अटैच होता है. शैडो में जो कुछ भी जोड़ा जाता है वह बन जाता है होस्ट करने वाले एलिमेंट के लिए लोकल, जिसमें <style> शामिल है. शैडो डीओएम ऐसा होता है सीएसएस स्टाइल की रेंज तय करती है.

शैडो DOM बनाया जा रहा है

शैडो रूट दस्तावेज़ का एक हिस्सा होता है, जो किसी “होस्ट” एलिमेंट के साथ जुड़ जाता है. शैडो रूट को अटैच करने की कार्रवाई से ही वह एलिमेंट अपने शैडो डीओएम हासिल कर लेता है. यहां की यात्रा पर हूं किसी एलिमेंट के लिए शैडो डीओएम बनाएं, element.attachShadow() को कॉल करें:

const header = document.createElement('header');
const shadowRoot = header.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>'; // Could also use appendChild().

// header.shadowRoot === shadowRoot
// shadowRoot.host === header

मैं शैडो रूट को भरने के लिए .innerHTML का इस्तेमाल कर रहा/रही हूं, लेकिन आप अन्य DOM का भी इस्तेमाल कर सकते हैं एपीआई. यह वेब है. हमारे पास विकल्प है.

यह जानकारी एलिमेंट की सूची के बारे में बताती है जो शैडो ट्री होस्ट नहीं कर सकता. एलिमेंट दिखने की कई वजहें हो सकती हैं इस सूची में शामिल हैं:

  • ब्राउज़र, एलिमेंट के लिए पहले से ही अपने शैडो डीओएम को होस्ट करता है (<textarea>, <input>).
  • एलिमेंट के लिए शैडो डीओएम (<img>) होस्ट करना कोई मतलब नहीं है.

उदाहरण के लिए, यह काम नहीं करता है:

    document.createElement('input').attachShadow({mode: 'open'});
    // Error. `<input>` cannot host shadow dom.

कस्टम एलिमेंट के लिए शैडो डीओएम बनाना

शैडो डीओएम खास तौर पर, पेजों को बनाते समय कस्टम एलिमेंट. शैडो डीओएम का इस्तेमाल करके एलिमेंट के एचटीएमएल, सीएसएस, और JS को अलग-अलग हिस्सों में बांटें. इस तरह, जिससे एक "वेब कॉम्पोनेंट" बन जाता है.

उदाहरण - कोई कस्टम एलिमेंट शैडो DOM को खुद से जोड़ता है, इसके DOM/CSS को एन्क्रिप्ट करके:

// Use custom elements API v1 to register a new HTML tag and define its JS behavior
// using an ES6 class. Every instance of <fancy-tab> will have this same prototype.
customElements.define('fancy-tabs', class extends HTMLElement {
    constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to <fancy-tabs>.
    const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `
        <style>#tabs { ... }</style> <!-- styles are scoped to fancy-tabs! -->
        <div id="tabs">...</div>
        <div id="panels">...</div>
    `;
    }
    ...
});

यहां कुछ दिलचस्प चीज़ें चल रही हैं. पहली बात यह है कि <fancy-tabs> के इंस्टेंस आने पर, कस्टम एलिमेंट अपना शैडो डीओएम बनाता है बनाया जाता है. constructor() में ऐसा किया जाता है. दूसरा, क्योंकि हम एक शैडो रूट है, तो <style> में मौजूद सीएसएस नियमों को <fancy-tabs> तक सीमित कर दिया जाएगा.

कंपोज़िशन और स्लॉट

कंपोज़िशन शैडो डीओएम की सबसे कम समझा जाने वाली सुविधाओं में से एक है, लेकिन यह साथ ही, यह सबसे ज़रूरी है.

वेब डेवलपमेंट की हमारी दुनिया में, कंपोज़िशन के ज़रिए हम ऐप्लिकेशन बनाते हैं, HTML से बाहर है. अलग-अलग बिल्डिंग ब्लॉक (<div>, <header>, <form>, <input>) एक साथ मिलकर ऐप्लिकेशन बनाते हैं. इनमें से कुछ टैग ऐसे भी काम करते हैं एक-दूसरे के साथ जुड़े रहें. कंपोज़िशन की वजह से नेटिव एलिमेंट, जैसे कि <select>, <details>, <form>, और <video> में ज़रूरत के हिसाब से बदलाव किए जा सकते हैं. उनमें से हर टैग स्वीकार करता है कुछ HTML). साथ ही, उनके साथ कुछ खास करता है. उदाहरण के लिए, <select> को ड्रॉपडाउन में <option> और <optgroup> को रेंडर करने का तरीका पता है और कई विकल्प चुनने वाले विजेट. <details> एलिमेंट, <summary> को बड़ा हो सकता है. <video> को भी पता है कि कुछ बच्चों के साथ कैसे काम करना है: <source> एलिमेंट रेंडर नहीं होते, लेकिन उनसे वीडियो के काम करने के तरीके पर असर पड़ता है. क्या बात है!

शब्दावली: लाइट डीओएम बनाम शैडो डीओएम

शैडो डीओएम कंपोज़िशन से वेब पर कई नई बुनियादी बातें पता चलती हैं डेवलपमेंट. खर-पतवार की जानकारी पाने से पहले, आइए इनमें से कुछ चीज़ों के बारे में जानते हैं तो हम एक ही भाषा का इस्तेमाल कर रहे हैं.

लाइट डीओएम

वह मार्कअप जिसे आपके कॉम्पोनेंट का इस्तेमाल करने वाला कोई उपयोगकर्ता लिखता है. यह डीओएम कॉम्पोनेंट के शैडो DOM. यह एलिमेंट के असली चाइल्ड हैं.

<better-button>
    <!-- the image and span are better-button's light DOM -->
    <img src="gear.svg" slot="icon">
    <span>Settings</span>
</better-button>

शैडो डीओएम

वह डीओएम जो कॉम्पोनेंट लेखक लिखता है. शैडो डीओएम, कॉम्पोनेंट और इसकी इंटरनल स्ट्रक्चर, स्कोप वाले सीएसएस को तय करता है, और लागू करने की प्रोसेस को एन्क्रिप्ट (सुरक्षित) करता है विवरण. इसमें यह भी बताया जा सकता है कि उपभोक्ता के लिखे मार्कअप को कैसे रेंडर किया जाए कॉम्पोनेंट का इस्तेमाल किया जा सकता है.

#shadow-root
    <style>...</style>
    <slot name="icon"></slot>
    <span id="wrapper">
    <slot>Button</slot>
    </span>

फ़्लैट किया गया डीओएम ट्री

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

<better-button>
    #shadow-root
    <style>...</style>
    <slot name="icon">
        <img src="gear.svg" slot="icon">
    </slot>
    <span id="wrapper">
        <slot>
        <span>Settings</span>
        </slot>
    </span>
</better-button>

<slot> एलिमेंट

शैडो डीओएम, <slot> एलिमेंट का इस्तेमाल करके अलग-अलग डीओएम ट्री बनाता है. स्लॉट आपके कॉम्पोनेंट में मौजूद प्लेसहोल्डर होते हैं, जिन्हें उपयोगकर्ता अपने कॉम्पोनेंट से भर सकते हैं खुद का मार्कअप बनाएं. एक या ज़्यादा स्लॉट तय करने का मतलब है कि रेंडर करने के लिए, बाहर के मार्कअप को न्योता भेजा जाएगा आपके कॉम्पोनेंट के शैडो DOM में. ज़रूरी है कि आप कह रहे हैं "इस उपयोगकर्ता को किसी मार्कअप यहां देखें".

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

कोई कॉम्पोनेंट अपने शैडो डीओएम में शून्य या उससे ज़्यादा स्लॉट तय कर सकता है. स्लॉट खाली हो सकते हैं या फ़ॉलबैक कॉन्टेंट उपलब्ध कराएं. अगर उपयोगकर्ता लाइट DOM नहीं देता है कॉन्टेंट होता है, तो स्लॉट अपने फ़ॉलबैक कॉन्टेंट को रेंडर करता है.

<!-- Default slot. If there's more than one default slot, the first is used. -->
<slot></slot>

<slot>fallback content</slot> <!-- default slot with fallback content -->

<slot> <!-- default slot entire DOM tree as fallback -->
    <h2>Title</h2>
    <summary>Description text</summary>
</slot>

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

उदाहरण - <fancy-tabs> के शैडो DOM में स्लॉट:

#shadow-root
    <div id="tabs">
    <slot id="tabsSlot" name="title"></slot> <!-- named slot -->
    </div>
    <div id="panels">
    <slot id="panelsSlot"></slot>
    </div>

कॉम्पोनेंट उपयोगकर्ता, <fancy-tabs> को इस तरह बताते हैं:

<fancy-tabs>
    <button slot="title">Title</button>
    <button slot="title" selected>Title 2</button>
    <button slot="title">Title 3</button>
    <section>content panel 1</section>
    <section>content panel 2</section>
    <section>content panel 3</section>
</fancy-tabs>

<!-- Using <h2>'s and changing the ordering would also work! -->
<fancy-tabs>
    <h2 slot="title">Title</h2>
    <section>content panel 1</section>
    <h2 slot="title" selected>Title 2</h2>
    <section>content panel 2</section>
    <h2 slot="title">Title 3</h2>
    <section>content panel 3</section>
</fancy-tabs>

अगर आप सोच रहे हैं कि चपटा पेड़ कुछ ऐसा दिखता है:

<fancy-tabs>
    #shadow-root
    <div id="tabs">
        <slot id="tabsSlot" name="title">
        <button slot="title">Title</button>
        <button slot="title" selected>Title 2</button>
        <button slot="title">Title 3</button>
        </slot>
    </div>
    <div id="panels">
        <slot id="panelsSlot">
        <section>content panel 1</section>
        <section>content panel 2</section>
        <section>content panel 3</section>
        </slot>
    </div>
</fancy-tabs>

ध्यान दें कि हमारा कॉम्पोनेंट अलग-अलग कॉन्फ़िगरेशन को हैंडल कर सकता है, लेकिन फ़्लैटन डीओएम ट्री पहले जैसा ही है. हम <button> से <h2>. इस कॉम्पोनेंट को अलग-अलग तरह के बच्चों को हैंडल करने के लिए बनाया गया है... सिर्फ़ जैसा कि <select> करता है!

शैलीकृत करना

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

कॉम्पोनेंट के हिसाब से तय की गई स्टाइल

शैडो डीओएम की सबसे फ़ायदेमंद सुविधा, स्कोप वाले सीएसएस को असाइन की जाती है:

  • बाहरी पेज के सीएसएस सिलेक्टर आपके कॉम्पोनेंट के अंदर लागू नहीं होते हैं.
  • अंदर तय की गई स्टाइल खत्म नहीं होती हैं. ये होस्ट एलिमेंट तक सीमित होते हैं.

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

उदाहरण - शैडो रूट में तय की गई स्टाइल स्थानीय हैं

#shadow-root
    <style>
    #panels {
        box-shadow: 0 2px 2px rgba(0, 0, 0, .3);
        background: white;
        ...
    }
    #tabs {
        display: inline-flex;
        ...
    }
    </style>
    <div id="tabs">
    ...
    </div>
    <div id="panels">
    ...
    </div>

स्टाइलशीट का दायरा भी शैडो ट्री तक का होता है:

#shadow-root
    <link rel="stylesheet" href="styles.css">
    <div id="tabs">
    ...
    </div>
    <div id="panels">
    ...
    </div>

क्या आपने कभी सोचा है कि <select> एलिमेंट, एक से ज़्यादा विकल्प वाले विजेट को रेंडर कैसे करता है एक ड्रॉपडाउन) तब दिया जाता है, जब multiple एट्रिब्यूट जोड़ा जाता है:

<select multiple>
  <option>Do</option>
  <option selected>Re</option>
  <option>Mi</option>
  <option>Fa</option>
  <option>So</option>
</select>

<select> आपके एट्रिब्यूट के आधार पर, खुद अलग तरीके से स्टाइल कर सकता है एलान करें. :host का इस्तेमाल करके, वेब कॉम्पोनेंट खुद को भी स्टाइल कर सकते हैं सिलेक्टर.

उदाहरण - कॉम्पोनेंट स्टाइलिंग

<style>
:host {
    display: block; /* by default, custom elements are display: inline */
    contain: content; /* CSS containment FTW. */
}
</style>

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

:host(<selector>) के फ़ंक्शनल फ़ॉर्म की मदद से, होस्ट को टारगेट किया जा सकता है, अगर वह <selector> से मेल खाता है. यह आपके कॉम्पोनेंट को एनकैप्सुलेट करने का एक शानदार तरीका है ऐसे व्यवहार जो उपयोगकर्ता के इंटरैक्शन या स्थिति या स्टाइल के हिसाब से इंटरनल नोड पर प्रतिक्रिया देते हैं होस्ट पर.

<style>
:host {
    opacity: 0.4;
    will-change: opacity;
    transition: opacity 300ms ease-in-out;
}
:host(:hover) {
    opacity: 1;
}
:host([disabled]) { /* style when host has disabled attribute. */
    background: grey;
    pointer-events: none;
    opacity: 0.4;
}
:host(.blue) {
    color: blue; /* color host when it has class="blue" */
}
:host(.pink) > #tabs {
    color: pink; /* color internal #tabs node when host has class="pink". */
}
</style>

कॉन्टेक्स्ट के हिसाब से स्टाइल

:host-context(<selector>), कॉम्पोनेंट से मेल खाता है. ऐसा तब होता है, जब यह कॉम्पोनेंट या उसका कोई ऐनसेस्टर हो <selector> से मेल खाता है. इसके लिए आम तौर पर, किसी कॉम्पोनेंट के आधार पर थीम का इस्तेमाल किया जाता है आस-पास. उदाहरण के लिए, कई लोग <html> या <body>:

<body class="darktheme">
    <fancy-tabs>
    ...
    </fancy-tabs>
</body>

जब यह डिसेंडेंट है, तो :host-context(.darktheme), <fancy-tabs> को स्टाइल करेगा .darktheme में से:

:host-context(.darktheme) {
    color: white;
    background: black;
}

थीम बनाने के लिए :host-context() काम का हो सकता है. हालांकि, इससे भी बेहतर तरीका यह है कि सीएसएस कस्टम प्रॉपर्टी का इस्तेमाल करके स्टाइल हुक बनाएं.

वितरित नोड को शैली देना

::slotted(<compound-selector>) उन नोड से मेल खाता है जिन्हें <slot>.

मान लें कि हमने एक नाम बैज घटक बनाया है:

<name-badge>
    <h2>Eric Bidelman</h2>
    <span class="title">
    Digital Jedi, <span class="company">Google</span>
    </span>
</name-badge>

कॉम्पोनेंट के शैडो डीओएम से, उपयोगकर्ता के <h2> और .title को स्टाइल किया जा सकता है:

<style>
::slotted(h2) {
    margin: 0;
    font-weight: 300;
    color: red;
}
::slotted(.title) {
    color: orange;
}
/* DOESN'T WORK (can only select top-level nodes).
::slotted(.company),
::slotted(.title .company) {
    text-transform: uppercase;
}
*/
</style>
<slot></slot>

अगर आपको पहले से याद है, तो <slot> उपयोगकर्ता के लाइट DOM को नहीं मूव करते हैं. टास्क कब शुरू होगा नोड को <slot> में बांटा जाता है और <slot> अपने DOM को रेंडर करता है, लेकिन नोड फ़िज़िकल तौर पर बने रहते हैं. डिस्ट्रिब्यूशन से पहले लागू की गई स्टाइल आगे भी बनी रहेंगी डिस्ट्रिब्यूशन के बाद लागू करें. हालांकि, जब लाइट DOM को डिस्ट्रिब्यूट किया जाता है, तो यह ऐसा हो सकता है अतिरिक्त स्टाइल (शैडो डीओएम से तय किए गए स्टाइल) को अपनाते हैं.

ज़्यादा जानकारी वाला एक और उदाहरण: <fancy-tabs> से मिला है:

const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
    <style>
    #panels {
        box-shadow: 0 2px 2px rgba(0, 0, 0, .3);
        background: white;
        border-radius: 3px;
        padding: 16px;
        height: 250px;
        overflow: auto;
    }
    #tabs {
        display: inline-flex;
        -webkit-user-select: none;
        user-select: none;
    }
    #tabsSlot::slotted(*) {
        font: 400 16px/22px 'Roboto';
        padding: 16px 8px;
        ...
    }
    #tabsSlot::slotted([aria-selected="true"]) {
        font-weight: 600;
        background: white;
        box-shadow: none;
    }
    #panelsSlot::slotted([aria-hidden="true"]) {
        display: none;
    }
    </style>
    <div id="tabs">
    <slot id="tabsSlot" name="title"></slot>
    </div>
    <div id="panels">
    <slot id="panelsSlot"></slot>
    </div>
`;

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

बाहरी हिस्से से किसी कॉम्पोनेंट का लुक तय करना

किसी कॉम्पोनेंट को बाहर से स्टाइल करने के कई तरीके हैं. सबसे आसान यहां टैग के नाम को सिलेक्टर के तौर पर इस्तेमाल किया जा सकता है:

fancy-tabs {
    width: 500px;
    color: red; /* Note: inheritable CSS properties pierce the shadow DOM boundary. */
}
fancy-tabs:hover {
    box-shadow: 0 3px 3px #ccc;
}

बाहरी स्टाइल हमेशा शैडो डीओएम में तय किए गए स्टाइल पर जीत हासिल करते हैं. उदाहरण के लिए, अगर उपयोगकर्ता सिलेक्टर fancy-tabs { width: 500px; } लिखता है, तो यह ट्रंप हो जाएगा कॉम्पोनेंट का नियम: :host { width: 650px;}.

कॉम्पोनेंट का स्टाइल बदलने से, आपको बेहतर नतीजे मिलेंगे. हालांकि, क्या होगा अगर आपको किसी कॉम्पोनेंट के अंदरूनी हिस्से को स्टाइल करना है? इसके लिए, हमें सीएसएस कस्टम प्रॉपर्टी.

सीएसएस कस्टम प्रॉपर्टी का इस्तेमाल करके स्टाइल हुक बनाना

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

उदाहरण - <fancy-tabs>, उपयोगकर्ताओं को बैकग्राउंड का रंग बदलने की अनुमति देता है:

<!-- main page -->
<style>
    fancy-tabs {
    margin-bottom: 32px;
    --fancy-tabs-bg: black;
    }
</style>
<fancy-tabs background>...</fancy-tabs>

इसके शैडो डीओएम के अंदर:

:host([background]) {
    background: var(--fancy-tabs-bg, #9E9E9E);
    border-radius: 10px;
    padding: 10px;
}

इस मामले में, कॉम्पोनेंट, बैकग्राउंड वैल्यू के तौर पर black का इस्तेमाल करेगा, उपयोगकर्ता ने इसे उपलब्ध कराया है. ऐसा न होने पर, यह डिफ़ॉल्ट रूप से #9E9E9E पर सेट होता है.

उन्नत विषय

बंद शैडो रूट बनाना (इससे बचना चाहिए)

शैडो डीओएम का एक और फ़्लेवर है, जिसे "क्लोज़्ड" कहा जाता है मोड. जब आप क्लोज़्ड शैडो ट्री, JavaScript के बाहर के इंटरनल डीओएम को ऐक्सेस नहीं कर पाएगा कॉम्पोनेंट का इस्तेमाल किया जा सकता है. यह <video> जैसे नेटिव एलिमेंट के काम करने के तरीके जैसा ही है. JavaScript <video> के शैडो DOM को ऐक्सेस नहीं कर सकता, क्योंकि ब्राउज़र इसे क्लोज़्ड-मोड शैडो रूट का इस्तेमाल करके लागू करता है.

उदाहरण - क्लोज़्ड शैडो ट्री बनाना:

const div = document.createElement('div');
const shadowRoot = div.attachShadow({mode: 'closed'}); // close shadow tree
// div.shadowRoot === null
// shadowRoot.host === div

क्लोज़्ड मोड का असर अन्य एपीआई पर भी पड़ता है:

  • Element.assignedSlot / TextNode.assignedSlot, null रिटर्न कर रहा है
  • शैडो में मौजूद एलिमेंट से जुड़े इवेंट के लिए Event.composedPath() DOM, [] लौटाता है

यहां बताया गया है कि आपको वेब कॉम्पोनेंट क्यों नहीं बनाने चाहिए {mode: 'closed'}:

  1. नकली सुरक्षा. हमलावर को किसी भी चीज़ से नहीं रोका जा सकता Element.prototype.attachShadow को हाइजैक करना.

  2. क्लोज़्ड मोड आपके कस्टम एलिमेंट कोड को खुद ऐक्सेस करने से रोकता है शैडो DOM. पूरी तरह से असफल. इसके बजाय, आपको रेफ़रंस को छिपाना होगा ताकि आप querySelector() जैसी चीज़ों का इस्तेमाल करना चाहें. यह पूरी तरह से क्लोज़्ड मोड के मूल मकसद को खारिज कर देता है!

        customElements.define('x-element', class extends HTMLElement {
        constructor() {
        super(); // always call super() first in the constructor.
        this._shadowRoot = this.attachShadow({mode: 'closed'});
        this._shadowRoot.innerHTML = '<div class="wrapper"></div>';
        }
        connectedCallback() {
        // When creating closed shadow trees, you'll need to stash the shadow root
        // for later if you want to use it again. Kinda pointless.
        const wrapper = this._shadowRoot.querySelector('.wrapper');
        }
        ...
    });
    
  3. क्लोज़्ड मोड में असली उपयोगकर्ताओं के लिए आपके कॉम्पोनेंट को कम सुविधाजनक बनाया जाता है. अगर आपने वेब कॉम्पोनेंट बनाने के लिए, एक समय आएगा जब आप सुविधा. कॉन्फ़िगरेशन का विकल्प. उपयोगकर्ता चाहता है कि इस्तेमाल का उदाहरण दिया जाए. एक कॉमन उदाहरण के लिए, अंदरूनी नोड के लिए सही स्टाइलिंग हुक शामिल न करना. क्लोज़्ड मोड के साथ, उपयोगकर्ताओं के लिए डिफ़ॉल्ट को ओवरराइड करने और ट्वीक करने का कोई तरीका नहीं है शैलियां. कॉम्पोनेंट के अंदर के हिस्सों को ऐक्सेस कर पाना बहुत मददगार होता है. आखिर में, उपयोगकर्ता आपके कॉम्पोनेंट को फ़ोर्क कर देंगे, कोई दूसरा कॉम्पोनेंट ढूंढेंगे या अपना अगर वह जो चाहती है वह नहीं करती :(

JS में स्लॉट के साथ काम करना

शैडो DOM एपीआई, स्लॉट और डिस्ट्रिब्यूटेड के साथ काम करने के लिए सुविधाएं देता है नोड. कस्टम एलिमेंट बनाते समय, ये तरीके काम आते हैं.

स्लॉटचेंज इवेंट

किसी स्लॉट के डिस्ट्रिब्यूटेड नोड में बदलाव होने पर, slotchange इवेंट ट्रिगर होता है. इसके लिए उदाहरण के लिए, अगर कोई उपयोगकर्ता लाइट DOM से बच्चों को जोड़ता/हटाता है.

const slot = this.shadowRoot.querySelector('#slot');
slot.addEventListener('slotchange', e => {
    console.log('light dom children changed!');
});

लाइट DOM में अन्य तरह के बदलावों पर नज़र रखने के लिए, आप MutationObserver आपके एलिमेंट के कंस्ट्रक्टर में.

किसी स्लॉट में कौनसे एलिमेंट रेंडर हो रहे हैं?

कभी-कभी यह जानना मददगार होता है कि किसी स्लॉट के साथ कौनसे एलिमेंट जुड़े हैं. कॉल करें स्लॉट किन एलिमेंट को रेंडर कर रहा है, यह पता लगाने के लिए slot.assignedNodes(). कॉन्टेंट बनाने अगर कोई नोड नहीं है, तो {flatten: true} विकल्प, स्लॉट का फ़ॉलबैक कॉन्टेंट भी दिखाएगा डिस्ट्रिब्यूट किए जा रहे हैं).

उदाहरण के लिए, मान लें कि आपका शैडो डीओएम कुछ ऐसा दिखता है:

<slot><b>fallback content</b></slot>
इस्तेमालकॉल करेंनतीजा
<my-component>घटक टेक्स्ट</my-component> slot.assignedNodes(); [component text]
&lt;my-component&gt;&lt;/my-component&gt; slot.assignedNodes(); []
&lt;my-component&gt;&lt;/my-component&gt; slot.assignedNodes({flatten: true}); [<b>fallback content</b>]

एलिमेंट किस स्लॉट को असाइन किया जाता है?

उलटे सवाल का जवाब भी दिया जा सकता है. element.assignedSlot बताता है कि आपके एलिमेंट को किस कॉम्पोनेंट स्लॉट में असाइन किया गया है.

शैडो डीओएम इवेंट मॉडल

जब कोई इवेंट शैडो डीओएम से बबल अप होता है, तो उसके टारगेट को इन बदलावों के साथ अडजस्ट किया जाता है: इनकैप्सुलेशन है, जो शैडो DOM से मिलता है. इसका मतलब है कि इवेंट को फिर से टारगेट किया जाता है, ताकि जैसे वे आपकी साइट के अंदर के एलिमेंट के बजाय कॉम्पोनेंट से आते हैं शैडो DOM. कुछ इवेंट, शैडो डीओएम से भी बाहर नहीं आते हैं.

ये इवेंट, शैडो सीमा को पार करते हैं:

  • फ़ोकस इवेंट: blur, focus, focusin, focusout
  • माउस इवेंट: click, dblclick, mousedown, mouseenter, mousemove वगैरह.
  • व्हील इवेंट: wheel
  • इनपुट इवेंट: beforeinput, input
  • कीबोर्ड इवेंट: keydown, keyup
  • कंपोज़िशन इवेंट: compositionstart, compositionupdate, compositionend
  • ड्रैगइवेंट: dragstart, drag, dragend, drop वगैरह.

सलाह

अगर शैडो ट्री खुला है, तो event.composedPath() को कॉल करने पर अरे दिखेगा नोड का पता लगाते हैं जिनसे इवेंट पूरा हुआ.

कस्टम इवेंट का इस्तेमाल करना

शैडो ट्री में आंतरिक नोड पर सक्रिय किए जाने वाले कस्टम DOM इवेंट शैडो सीमा से बाहर बबल तब तक डालें, जब तक कि composed: true फ़्लैग:

// Inside <fancy-tab> custom element class definition:
selectTab() {
    const tabs = this.shadowRoot.querySelector('#tabs');
    tabs.dispatchEvent(new Event('tab-select', {bubbles: true, composed: true}));
}

अगर composed: false (डिफ़ॉल्ट सेटिंग) लागू है, तो उपभोक्ता इवेंट नहीं सुन सकेंगे की मदद से बाहर रखा जा सकता है.

<fancy-tabs></fancy-tabs>
<script>
    const tabs = document.querySelector('fancy-tabs');
    tabs.addEventListener('tab-select', e => {
    // won't fire if `tab-select` wasn't created with `composed: true`.
    });
</script>

फ़ोकस हैंडलिंग

अगर आपको शैडो डीओएम के इवेंट मॉडल से याद आता है, तो ट्रिगर होने वाले इवेंट शैडो डीओएम को इस तरह अडजस्ट किया जाता है कि वे होस्टिंग एलिमेंट से मिले हों. उदाहरण के लिए, मान लें कि आपने शैडो रूट के अंदर <input> पर क्लिक किया है:

<x-focus>
    #shadow-root
    <input type="text" placeholder="Input inside shadow dom">

focus इवेंट ऐसा दिखेगा कि यह <x-focus> से आया है, <input> से नहीं. इसी तरह, document.activeElement का मान <x-focus> होगा. अगर शैडो रूट को mode:'open' की मदद से बनाया गया था (बंद मोड देखें), तो आप यह भी करेंगे फ़ोकस पाने वाले इंटरनल नोड को ऐक्सेस कर पाएगा:

document.activeElement.shadowRoot.activeElement // only works with open mode.

अगर चल रहे शैडो डीओएम के कई लेवल हैं (जैसे, करने के लिए आपको शैडो रूट में बार-बार ड्रिल करना होगा, ताकि activeElement ढूंढें:

function deepActiveElement() {
    let a = document.activeElement;
    while (a && a.shadowRoot && a.shadowRoot.activeElement) {
    a = a.shadowRoot.activeElement;
    }
    return a;
}

फ़ोकस करने के लिए दूसरा विकल्प delegatesFocus: true है. यह विकल्प को बड़ा करता है शैडो ट्री के अंदर एलीमेंट का फ़ोकस व्यवहार:

  • अगर शैडो डीओएम के अंदर किसी नोड पर क्लिक किया जाता है और नोड, फ़ोकस करने लायक एरिया नहीं है, पहला काम फ़ोकस किया जा सकता है.
  • जब शैडो डीओएम के अंदर का कोई नोड फ़ोकस हासिल करता है, तो :focus जोड़ सकते हैं.

उदाहरण - delegatesFocus: true फ़ोकस के व्यवहार में कैसे बदलाव करता है

<style>
    :focus {
    outline: 2px solid red;
    }
</style>

<x-focus></x-focus>

<script>
customElements.define('x-focus', class extends HTMLElement {
    constructor() {
    super(); // always call super() first in the constructor.

    const root = this.attachShadow({mode: 'open', delegatesFocus: true});
    root.innerHTML = `
        <style>
        :host {
            display: flex;
            border: 1px dotted black;
            padding: 16px;
        }
        :focus {
            outline: 2px solid blue;
        }
        </style>
        <div>Clickable Shadow DOM text</div>
        <input type="text" placeholder="Input inside shadow dom">`;

    // Know the focused element inside shadow DOM:
    this.addEventListener('focus', function(e) {
        console.log('Active element (inside shadow dom):',
                    this.shadowRoot.activeElement);
    });
    }
});
</script>

नतीजा

डेलिगेट के लिए: सही व्यवहार.

ऊपर दिखाया गया नतीजा है कि <x-focus> पर फ़ोकस किया गया है (उपयोगकर्ता का क्लिक, इस पर टैब किया गया, focus() वगैरह), "क्लिक किए जा सकने वाले शैडो डीओएम टेक्स्ट" क्लिक किया गया हो या इंटरनल <input> फ़ोकस है (autofocus शामिल है).

अगर आपको delegatesFocus: false को सेट करना होता, तो इसके बजाय आपको यह दिखेगा:

डेलिगेट फ़ोकस: गलत है और इंटरनल इनपुट पर फ़ोकस किया गया है.
delegatesFocus: false और अंदरूनी <input> पर फ़ोकस किया गया है.
डेलिगेट फ़ोकस: गलत और x-फ़ोकस
    फ़ोकस हासिल करता है (जैसे, इसमें tabindex=&#39;0&#39; होता है).
delegatesFocus: false और <x-focus> फ़ोकस बढ़ता है (जैसे कि इसमें tabindex="0" है).
डेलिगेट फ़ोकस: गलत और &#39;क्लिक किए जा सकने वाले शैडो डीओएम टेक्स्ट&#39; इससे मेल खाता है
    क्लिक किया गया हो (या एलिमेंट के शैडो डीओएम में मौजूद किसी खाली एरिया पर क्लिक किया गया हो).
delegatesFocus: false और "क्लिक किए जा सकने वाले शैडो DOM टेक्स्ट" इससे मेल खाता है क्लिक किया गया हो (या एलिमेंट के शैडो डीओएम में मौजूद किसी खाली एरिया पर क्लिक किया गया हो).

सुझाव और तरकीबें

पिछले कुछ सालों में मैंने वेब कॉम्पोनेंट बनाने के बारे में कुछ बातें सीखी हैं. मैं आपको लगता है कि इनमें से कुछ सलाह कॉम्पोनेंट, शैडो डीओएम को डीबग करना.

सीएसएस कंटेनमेंट का इस्तेमाल करें

आम तौर पर, वेब कॉम्पोनेंट का लेआउट/स्टाइल/पेंट अपने-आप में पूरी तरह शामिल होता है. इस्तेमाल की जाने वाली चीज़ें परफ़ॉर्मेंस के लिए :host में सीएसएस कंटेनमेंट जीत:

<style>
:host {
    display: block;
    contain: content; /* Boom. CSS containment FTW. */
}
</style>

इनहेरिट किए जा सकने वाले स्टाइल रीसेट किए जा रहे हैं

इनहेरिट की जा सकने वाली स्टाइल (background, color, font, line-height वगैरह) जारी हैं शैडो DOM में इनहेरिट करने के लिए. इसका मतलब है कि वे शैडो DOM सीमा को डिफ़ॉल्ट. अगर आपको नए स्लेट से शुरू करना है, तो रीसेट करने के लिए all: initial; का इस्तेमाल करें शैडो सीमा पार करने पर, इनहेरिट करने लायक स्टाइल अपनी शुरुआती वैल्यू में बदल जाते हैं.

<style>
    div {
    padding: 10px;
    background: red;
    font-size: 25px;
    text-transform: uppercase;
    color: white;
    }
</style>

<div>
    <p>I'm outside the element (big/white)</p>
    <my-element>Light DOM content is also affected.</my-element>
    <p>I'm outside the element (big/white)</p>
</div>

<script>
const el = document.querySelector('my-element');
el.attachShadow({mode: 'open'}).innerHTML = `
    <style>
    :host {
        all: initial; /* 1st rule so subsequent properties are reset. */
        display: block;
        background: white;
    }
    </style>
    <p>my-element: all CSS properties are reset to their
        initial value using <code>all: initial</code>.</p>
    <slot></slot>
`;
</script>

किसी पेज पर इस्तेमाल किए गए सभी कस्टम एलिमेंट को ढूंढना

कभी-कभी पेज पर इस्तेमाल किए गए कस्टम एलिमेंट को ढूंढना मददगार होता है. ऐसा करने के लिए, आपको पेज पर इस्तेमाल किए गए सभी एलिमेंट के शैडो डीओएम को बार-बार ट्रैवर्स करना ज़रूरी है.

const allCustomElements = [];

function isCustomElement(el) {
    const isAttr = el.getAttribute('is');
    // Check for <super-button> and <button is="super-button">.
    return el.localName.includes('-') || isAttr && isAttr.includes('-');
}

function findAllCustomElements(nodes) {
    for (let i = 0, el; el = nodes[i]; ++i) {
    if (isCustomElement(el)) {
        allCustomElements.push(el);
    }
    // If the element has shadow DOM, dig deeper.
    if (el.shadowRoot) {
        findAllCustomElements(el.shadowRoot.querySelectorAll('*'));
    }
    }
}

findAllCustomElements(document.querySelectorAll('*'));

किसी <template> से एलिमेंट बनाना

.innerHTML का इस्तेमाल करके शैडो रूट की जानकारी अपने-आप भरने के बजाय, हम डिक्लेरेटिव टोन का इस्तेमाल कर सकते हैं <template>. टेंप्लेट यह जानकारी देने के लिए सबसे सही प्लेसहोल्डर होते हैं एक वेब घटक है.

इसका उदाहरण यहां देखें "कस्टम एलिमेंट: फिर से इस्तेमाल किए जा सकने वाले वेब कॉम्पोनेंट बनाना".

इतिहास और ब्राउज़र सहायता

अगर पिछले कुछ सालों से वेब कॉम्पोनेंट को फ़ॉलो किया जा रहा है, तो यह जान लें कि Chrome 35+/Opera शैडो DOM के पुराने वर्शन को कभी-कभी. कुछ ब्राउज़र के लिए Blink साथ-साथ दोनों वर्शन पर काम करता रहेगा समय. v0 शर्त ने शैडो रूट बनाने का एक अलग तरीका दिया है (वर्शन 1 के element.attachShadow के बजाय element.createShadowRoot). कॉल पुराना तरीका v0 सिमैंटिक के साथ शैडो रूट बनाना जारी रखता है, इसलिए मौजूदा v0 कोड काम नहीं करेगा.

अगर आपको पुराने v0 स्पेसिफ़िकेशन में दिलचस्पी है, तो html5rocks देखें लेख: 1, 2, 3. दोनों पक्षों के बीच, शैडो DOM v0 और v1 के बीच अंतर.

ब्राउज़र समर्थन

Shadow DOM v1 को Chrome 53 में शिप किया गया (स्थिति), Opera 40, Safari 10, और Firefox 63. किनारे ने डेवलपमेंट शुरू कर दिया है.

शैडो डीओएम का पता लगाने की सुविधा के लिए, attachShadow की मौजूदगी की जांच करें:

const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;

पॉलीफ़िल

जब तक ब्राउज़र समर्थन व्यापक रूप से उपलब्ध नहीं हो जाता, तब तक shadydom और shadycss पॉलीफ़िल से आपको v1 मिलता है सुविधा. शेडी डीओएम, शैडो डीओएम और शैडीक्स पॉलीफ़िल के डीओएम स्कोपिंग जैसा बनाता है सीएसएस कस्टम प्रॉपर्टी और नेटिव एपीआई से मिलने वाली स्टाइल.

पॉलीफ़िल इंस्टॉल करें:

bower install --save webcomponents/shadydom
bower install --save webcomponents/shadycss

पॉलीफ़िल का इस्तेमाल करें:

function loadScript(src) {
    return new Promise(function(resolve, reject) {
    const script = document.createElement('script');
    script.async = true;
    script.src = src;
    script.onload = resolve;
    script.onerror = reject;
    document.head.appendChild(script);
    });
}

// Lazy load the polyfill if necessary.
if (!supportsShadowDOMV1) {
    loadScript('/bower_components/shadydom/shadydom.min.js')
    .then(e => loadScript('/bower_components/shadycss/shadycss.min.js'))
    .then(e => {
        // Polyfills loaded.
    });
} else {
    // Native shadow dom v1 support. Go to go!
}

https://github.com/webcomponents/shadycss#usage देखें देखें.

नतीजा

पहली बार, हमारे पास ऐसा एपीआई प्रिमिटिव है जो सही सीएसएस स्कोपिंग, DOM स्कोपिंग और इसमें सही कंपोज़िशन है. अन्य वेब कॉम्पोनेंट एपीआई के साथ शैडो डीओएम, कस्टम एलिमेंट की तरह ही टेक्स्ट को एनकैप्सुलेट करने का तरीका उपलब्ध कराता है बिना हैकिंग के या <iframe> जैसे पुराने बैगेज का इस्तेमाल करने वाले कॉम्पोनेंट.

मुझसे कोई गलती न करें. शैडो डीओएम वाकई एक मुश्किल जीव है! लेकिन यह एक जानवर है सीखने लायक था. इसके साथ कुछ समय बिताएं. इसे जानें और सवाल पूछें!

इसके बारे में और पढ़ें

अक्सर पूछे जाने वाले सवाल

क्या आज Shadow DOM v1 का इस्तेमाल किया जा सकता है?

पॉलीफ़िल के साथ हां. ब्राउज़र के लिए सहायता देखें.

शैडो डीओएम से सुरक्षा से जुड़ी कौनसी सुविधाएं मिलती हैं?

शैडो डीओएम, सुरक्षा की सुविधा नहीं है. सीएसएस का दायरा तय करने के लिए यह एक आसान टूल है और कॉम्पोनेंट में डीओएम ट्री को छिपाना. अगर आपको सुरक्षा की सही सीमा चाहिए, <iframe> का इस्तेमाल करें.

क्या किसी वेब कॉम्पोनेंट को शैडो डीओएम का इस्तेमाल करना ज़रूरी है?

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

खुले और बंद शैडो रूट में क्या अंतर है?

बंद शैडो रूट देखें.