शैडो DOM की मदद से, वेब डेवलपर वेब कॉम्पोनेंट के लिए अलग-अलग DOM और सीएसएस बना सकते हैं
खास जानकारी
शैडो डीओएम, वेब ऐप्लिकेशन बनाने की प्रोसेस को आसान बनाता है. यह समस्या, एचटीएमएल, सीएसएस, और JS के ग्लोबल नेचर की वजह से आती है. इन समस्याओं को हल करने के लिए, हमने सालों से कई टूल
बनाए
हैं. उदाहरण के लिए, जब किसी नए एचटीएमएल आईडी/क्लास का इस्तेमाल किया जाता है, तो यह नहीं बताया जा सकता कि वह पेज पर इस्तेमाल किए गए किसी मौजूदा नाम से मेल खाएगा या नहीं.
छोटी-मोटी गड़बड़ियां सामने आती हैं, सीएसएस की खास जानकारी एक बड़ी समस्या बन जाती है (!important सभी चीज़ें!), स्टाइल सिलेक्टर कंट्रोल से बाहर हो जाते हैं, और परफ़ॉर्मेंस पर असर पड़ सकता है. इस तरह के और भी कई उदाहरण हैं.
शैडो डीओएम, सीएसएस और डीओएम को ठीक करता है. यह वेब प्लैटफ़ॉर्म पर स्कोप की गई स्टाइल को शामिल करता है. टूल या नाम रखने के तरीके के बिना, सीएसएस को मार्कअप के साथ बंडल किया जा सकता है, लागू करने की जानकारी छिपाई जा सकती है, और वैनिला JavaScript में अपने-आप काम करने वाले कॉम्पोनेंट बनाए जा सकते हैं.
परिचय
शैडो डीओएम, वेब कॉम्पोनेंट के तीन स्टैंडर्ड में से एक है: एचटीएमएल टेंप्लेट, शैडो डीओएम, और कस्टम एलिमेंट. एचटीएमएल इंपोर्ट, पहले इस सूची का हिस्सा हुआ करते थे. हालांकि, अब इन्हें अब इस्तेमाल नहीं किया जाता के तौर पर मार्क किया गया है.
आपको शैडो डीओएम का इस्तेमाल करने वाले वेब कॉम्पोनेंट बनाने की ज़रूरत नहीं है. लेकिन जब आप ऐसा करते हैं, तो आपको इसके फ़ायदों (सीएसएस स्कोपिंग, डीओएम एनकैप्सुलेशन, कंपोज़िशन) का फ़ायदा मिलता है और फिर से इस्तेमाल किए जा सकने वाले कस्टम एलिमेंट बनाए जाते हैं, जो मज़बूत, आसानी से कॉन्फ़िगर किए जा सकने वाले, और फिर से इस्तेमाल किए जा सकने वाले होते हैं. अगर कस्टम एलिमेंट, JS API की मदद से नया एचटीएमएल बनाने का तरीका है, तो शैडो DOM, एचटीएमएल और सीएसएस उपलब्ध कराने का तरीका है. ये दोनों एपीआई मिलकर एक कॉम्पोनेंट बनाते हैं. इसमें एचटीएमएल, सीएसएस, और JavaScript शामिल होते हैं.
शैडो डीओएम को कॉम्पोनेंट पर आधारित ऐप्लिकेशन बनाने के लिए एक टूल के तौर पर डिज़ाइन किया गया है. इसलिए, यह वेब डेवलपमेंट में आने वाली सामान्य समस्याओं का समाधान करता है:
- अलग किया गया डीओएम: किसी कॉम्पोनेंट का डीओएम अपने-आप में पूरा होता है. उदाहरण के लिए,
document.querySelector()कॉम्पोनेंट के शैडो डीओएम में नोड नहीं दिखाएगा. - स्कोप वाली सीएसएस: शैडो डीओएम के अंदर तय की गई सीएसएस, उसी के लिए स्कोप की जाती है. स्टाइल के नियम लीक नहीं होते और पेज की स्टाइल में कोई बदलाव नहीं होता.
- कंपोज़िशन: अपने कॉम्पोनेंट के लिए, डिक्लेरेटिव और मार्कअप-आधारित एपीआई डिज़ाइन करें.
- सीएसएस को आसान बनाता है - स्कोप्ड डीओएम का मतलब है कि आसान सीएसएस सिलेक्टर, ज़्यादा सामान्य आईडी/क्लास के नाम इस्तेमाल किए जा सकते हैं. साथ ही, नाम से जुड़े विवादों की चिंता करने की ज़रूरत नहीं है.
- प्रॉडक्टिविटी - ऐप्लिकेशन को एक बड़े (ग्लोबल) पेज के बजाय, डीओएम के हिस्सों में बांटें.
fancy-tabs डेमो
इस लेख में, मैं एक डेमो कॉम्पोनेंट (<fancy-tabs>) का ज़िक्र करूंगा और उससे कोड स्निपेट का रेफ़रंस दूंगा. अगर आपका ब्राउज़र एपीआई के साथ काम करता है, तो आपको ठीक नीचे इसका लाइव डेमो दिखेगा. इसके अलावा, GitHub पर पूरा सोर्स देखें.
शैडो डीओएम क्या है?
डीओएम के बारे में जानकारी
एचटीएमएल की मदद से वेब पर काम करना आसान हो जाता है. कुछ टैग का इस्तेमाल करके, कुछ ही सेकंड में ऐसा पेज बनाया जा सकता है जिसमें प्रज़ेंटेशन और स्ट्रक्चर, दोनों हों. हालांकि, एचटीएमएल अपने-आप में ज़्यादा काम का नहीं है. इंसानों के लिए टेक्स्ट पर आधारित भाषा को समझना आसान होता है, लेकिन मशीनों को कुछ और चाहिए होता है. डॉक्यूमेंट ऑब्जेक्ट मॉडल या 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 का इस्तेमाल कर रहा हूं. हालांकि, अन्य डीओएम एपीआई का भी इस्तेमाल किया जा सकता है. यह वेब है. हमारे पास विकल्प हैं.
स्पेसिफ़िकेशन में ऐसे एलिमेंट की सूची दी गई है जो शैडो ट्री को होस्ट नहीं कर सकते. किसी एलिमेंट को सूची में शामिल करने की कई वजहें हो सकती हैं:
- ब्राउज़र में पहले से ही एलिमेंट (
<textarea>,<input>) के लिए, अपना इंटरनल शैडो DOM होस्ट होता है. - एलिमेंट के लिए, शैडो डीओएम (
<img>) को होस्ट करना सही नहीं है.
उदाहरण के लिए, यह काम नहीं करता:
document.createElement('input').attachShadow({mode: 'open'});
// Error. `<input>` cannot host shadow dom.
कस्टम एलिमेंट के लिए शैडो डीओएम बनाना
शैडो डीओएम, कस्टम एलिमेंट बनाते समय काफ़ी काम आता है. किसी एलिमेंट के एचटीएमएल, सीएसएस, और JS को अलग-अलग करने के लिए, शैडो डीओएम का इस्तेमाल करें. इससे एक "वेब कॉम्पोनेंट" बनता है.
उदाहरण - पसंद के मुताबिक बनाया गया कोई एलिमेंट, शैडो डीओएम को खुद से अटैच करता है. इससे, उसके डीओएम/सीएसएस को एनकैप्सुलेट किया जाता है:
// 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> का इंस्टेंस बनने पर, कस्टम एलिमेंट अपना शैडो DOM बनाता है. यह काम constructor() में किया जाता है. दूसरा, हम शैडो रूट बना रहे हैं. इसलिए, <style> के अंदर मौजूद सीएसएस नियम, <fancy-tabs> के दायरे में होंगे.
कंपोज़िशन और स्लॉट
कंपोज़िशन, शैडो डीओएम की सबसे कम समझी जाने वाली सुविधाओं में से एक है. हालांकि, यह सबसे अहम सुविधाओं में से एक है.
वेब डेवलपमेंट की दुनिया में, कंपोज़िशन का मतलब है कि हम एचटीएमएल का इस्तेमाल करके, ऐप्लिकेशन कैसे बनाते हैं. ऐप्लिकेशन बनाने के लिए, अलग-अलग बिल्डिंग ब्लॉक (<div>, <header>, <form>, <input>) एक साथ आते हैं. इनमें से कुछ टैग, एक-दूसरे के साथ भी काम करते हैं. कंपोज़िशन की वजह से ही, <select>, <details>, <form>, और <video> जैसे नेटिव एलिमेंट इतने फ़्लेक्सिबल होते हैं. इनमें से हर टैग, कुछ एचटीएमएल को चाइल्ड के तौर पर स्वीकार करता है और उनके साथ कुछ खास करता है. उदाहरण के लिए, <select> को पता है कि <option> और <optgroup> को ड्रॉपडाउन और कई विकल्प चुनने की सुविधा देने वाले विजेट में कैसे रेंडर करना है. <details> एलिमेंट, <summary> को बड़ा किए जा सकने वाले ऐरो के तौर पर रेंडर करता है. यहां तक कि <video> को भी पता है कि कुछ चाइल्ड एलिमेंट को कैसे मैनेज करना है:
<source> एलिमेंट रेंडर नहीं होते, लेकिन वे वीडियो के व्यवहार पर असर डालते हैं.
क्या जादू है!
शब्दावली: लाइट डीओएम बनाम शैडो डीओएम
शैडो डीओएम कंपोज़िशन, वेब डेवलपमेंट में कई नए बुनियादी सिद्धांत पेश करता है. बारीकियों में जाने से पहले, आइए कुछ शब्दावली को स्टैंडर्ड बना लें, ताकि हम एक ही भाषा में बात कर सकें.
लाइट डीओएम
आपके कॉम्पोनेंट का इस्तेमाल करने वाले व्यक्ति का लिखा गया मार्कअप. यह डीओएम, कॉम्पोनेंट के शैडो डीओएम के बाहर मौजूद होता है. यह एलिमेंट का असल चाइल्ड एलिमेंट होता है.
<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>
फ़्लैट किया गया डीओएम ट्री
ब्राउज़र, उपयोगकर्ता के लाइट डीओएम को आपके शैडो डीओएम में डिस्ट्रिब्यूट करता है. इससे फ़ाइनल प्रॉडक्ट रेंडर होता है. फ़्लैट किया गया ट्री, वह होता है जो आपको 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> एलिमेंट का इस्तेमाल करके अलग-अलग डीओएम ट्री को एक साथ जोड़ता है.
स्लॉट, आपके कॉम्पोनेंट में मौजूद प्लेसहोल्डर होते हैं. उपयोगकर्ता इन्हें अपने मार्कअप से भर सकते हैं. एक या उससे ज़्यादा स्लॉट तय करके, बाहरी मार्कअप को अपने कॉम्पोनेंट के शैडो डीओएम में रेंडर करने के लिए न्योता दिया जाता है. इसका मतलब है कि आपने कहा है कि "उपयोगकर्ता का मार्कअप यहां रेंडर करें".
जब कोई <slot> एलिमेंट को न्योता देता है, तो उन्हें शैडो DOM की सीमा को "पार" करने की अनुमति होती है. इन एलिमेंट को डिस्ट्रिब्यूटेड नोड कहा जाता है. कॉन्सेप्ट के हिसाब से,
डिस्ट्रिब्यूटेड नोड थोड़े अजीब लग सकते हैं. स्लॉट, डीओएम को फ़िज़िकल तौर पर नहीं ले जाते. वे इसे शैडो डीओएम में किसी दूसरी जगह पर रेंडर करते हैं.
कोई कॉम्पोनेंट, अपने शैडो 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> करता है!
शैलीकृत करना
वेब कॉम्पोनेंट को स्टाइल करने के लिए कई विकल्प मौजूद हैं. शैडो डीओएम का इस्तेमाल करने वाले कॉम्पोनेंट को मुख्य पेज से स्टाइल किया जा सकता है. साथ ही, उसकी अपनी स्टाइल तय की जा सकती हैं या उपयोगकर्ताओं को डिफ़ॉल्ट स्टाइल बदलने के लिए, हुक (सीएसएस कस्टम प्रॉपर्टी के तौर पर) उपलब्ध कराए जा सकते हैं.
कॉम्पोनेंट के हिसाब से तय की गई स्टाइल
शैडो डीओएम की सबसे काम की सुविधा, स्कोप की गई सीएसएस है:
- बाहरी पेज के सीएसएस सिलेक्टर, आपके कॉम्पोनेंट पर लागू नहीं होते.
- इसके अंदर तय की गई स्टाइल, बाहर नहीं दिखती हैं. ये होस्ट एलिमेंट के दायरे में होते हैं.
शैडो डीओएम में इस्तेमाल किए गए सीएसएस सिलेक्टर, आपके कॉम्पोनेंट पर स्थानीय तौर पर लागू होते हैं. इसका मतलब है कि हम पेज पर कहीं और होने वाले टकराव की चिंता किए बिना, सामान्य आईडी/क्लास के नामों का फिर से इस्तेमाल कर सकते हैं. शैडो डीओएम में आसान सीएसएस सिलेक्टर का इस्तेमाल करना सबसे सही तरीका है. इनसे परफ़ॉर्मेंस भी बेहतर होती है.
उदाहरण - शैडो रूट में तय की गई स्टाइल, लोकल होती हैं
#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>
क्या आपने कभी सोचा है कि multiple एट्रिब्यूट जोड़ने पर, <select> एलिमेंट ड्रॉपडाउन के बजाय, कई विकल्प चुनने की सुविधा देने वाला विजेट कैसे रेंडर करता है:
<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>
कॉन्टेक्स्ट के आधार पर स्टाइलिंग
अगर कॉम्पोनेंट या उसके पैरंट कॉम्पोनेंट में से कोई भी <selector> से मैच करता है, तो :host-context(<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> उपयोगकर्ता के लाइट डीओएम को नहीं हटाते. जब नोड को <slot> में डिस्ट्रिब्यूट किया जाता है, तो <slot> उनके डीओएम को रेंडर करता है. हालांकि, नोड अपनी जगह पर ही रहते हैं. डिस्ट्रिब्यूशन से पहले लागू की गई स्टाइल, डिस्ट्रिब्यूशन के बाद भी लागू रहती हैं. हालांकि, लाइट डीओएम को डिस्ट्रिब्यूट करने पर, यह अन्य स्टाइल अपना सकता है. ये स्टाइल, शैडो डीओएम से तय की जाती हैं.
<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>
शैडो DOM में:
:host([background]) {
background: var(--fancy-tabs-bg, #9E9E9E);
border-radius: 10px;
padding: 10px;
}
इस मामले में, कॉम्पोनेंट बैकग्राउंड वैल्यू के तौर पर black का इस्तेमाल करेगा, क्योंकि उपयोगकर्ता ने इसे उपलब्ध कराया है. ऐसा न करने पर, यह डिफ़ॉल्ट रूप से #9E9E9E पर सेट हो जाएगा.
उन्नत विषय
क्लोज़्ड शैडो रूट बनाना (इससे बचना चाहिए)
शैडो डीओएम का एक और फ़्लेवर है, जिसे "क्लोज़्ड" मोड कहा जाता है. क्लोज़्ड शैडो ट्री बनाने पर, बाहरी JavaScript आपके कॉम्पोनेंट के इंटरनल DOM को ऐक्सेस नहीं कर पाएगी. यह <video> जैसे नेटिव एलिमेंट के काम करने के तरीके से मिलता-जुलता है.
JavaScript, <video> के शैडो डीओएम को ऐक्सेस नहीं कर सकता. इसकी वजह यह है कि ब्राउज़र इसे क्लोज़्ड-मोड शैडो रूट का इस्तेमाल करके लागू करता है.
उदाहरण - क्लोज़्ड शैडो ट्री बनाना:
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()शैडो डीओएम के अंदर मौजूद एलिमेंट से जुड़े इवेंट के लिए, [] दिखाता है
यहां इस बारे में खास जानकारी दी गई है कि आपको {mode: 'closed'} का इस्तेमाल करके वेब कॉम्पोनेंट क्यों नहीं बनाने चाहिए:
सुरक्षा का झूठा एहसास. हमलावर को
Element.prototype.attachShadowको हाइजैक करने से कोई नहीं रोक सकता.क्लोज़्ड मोड, आपके कस्टम एलिमेंट कोड को उसके शैडो डीओएम को ऐक्सेस करने से रोकता है. यह पूरी तरह से नाकाम रहा. इसके बजाय, अगर आपको
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'); } ... });क्लोज़्ड मोड की वजह से, असली उपयोगकर्ताओं के लिए आपके कॉम्पोनेंट को इस्तेमाल करना कम आसान हो जाता है. वेब कॉम्पोनेंट बनाते समय, ऐसा हो सकता है कि आप कोई सुविधा जोड़ना भूल जाएं. कॉन्फ़िगरेशन का विकल्प. उपयोगकर्ता के लिए इस्तेमाल का कोई उदाहरण. इसका एक आम उदाहरण है, इंटरनल नोड के लिए ज़रूरी स्टाइलिंग हुक शामिल करना भूल जाना. क्लोज़्ड मोड में, उपयोगकर्ता डिफ़ॉल्ट सेटिंग को नहीं बदल सकते और स्टाइल में बदलाव नहीं कर सकते. कॉम्पोनेंट के इंटरनल को ऐक्सेस करने की सुविधा बहुत मददगार होती है. अगर आपका कॉम्पोनेंट उपयोगकर्ताओं की ज़रूरत के मुताबिक काम नहीं करता है, तो वे आपके कॉम्पोनेंट को फ़ोर्क करेंगे, कोई दूसरा कॉम्पोनेंट ढूंढेंगे या अपना कॉम्पोनेंट बनाएंगे :(
JS में स्लॉट के साथ काम करना
शैडो डीओएम एपीआई, स्लॉट और डिस्ट्रिब्यूटेड नोड के साथ काम करने के लिए सुविधाएं उपलब्ध कराता है. कस्टम एलिमेंट बनाते समय, ये काम आते हैं.
slotchange इवेंट
slotchange इवेंट तब ट्रिगर होता है, जब किसी स्लॉट के डिस्ट्रिब्यूट किए गए नोड में बदलाव होता है. उदाहरण के लिए, अगर उपयोगकर्ता लाइट डीओएम से चाइल्ड एलिमेंट जोड़ता है या हटाता है.
const slot = this.shadowRoot.querySelector('#slot');
slot.addEventListener('slotchange', e => {
console.log('light dom children changed!');
});
लाइट डीओएम में अन्य तरह के बदलावों पर नज़र रखने के लिए, अपने एलिमेंट के कंस्ट्रक्टर में MutationObserver सेट अप किया जा सकता है.
स्लॉट में कौनसे एलिमेंट रेंडर किए जा रहे हैं?
कभी-कभी यह जानना काम का होता है कि किसी स्लॉट से कौनसे एलिमेंट जुड़े हैं. slot.assignedNodes() को कॉल करें, ताकि यह पता लगाया जा सके कि स्लॉट किन एलिमेंट को रेंडर कर रहा है. {flatten: true} विकल्प, स्लॉट का फ़ॉलबैक कॉन्टेंट भी दिखाएगा. ऐसा तब होगा, जब कोई नोड डिस्ट्रिब्यूट न किया जा रहा हो.
उदाहरण के लिए, मान लें कि आपका शैडो DOM ऐसा दिखता है:
<slot><b>fallback content</b></slot>
| इस्तेमाल | कॉल करें | नतीजा |
|---|---|---|
| <my-component>component text</my-component> | slot.assignedNodes(); |
[component text] |
| <my-component></my-component> | slot.assignedNodes(); |
[] |
| <my-component></my-component> | slot.assignedNodes({flatten: true}); |
[<b>fallback content</b>] |
एलिमेंट को कौनसा स्लॉट असाइन किया गया है?
इसके उलट, यह भी बताया जा सकता है कि किसी खास तरह के कॉन्टेंट को किस तरह के दर्शक पसंद करते हैं. element.assignedSlot से आपको पता चलता है कि आपके एलिमेंट को कॉम्पोनेंट के किस स्लॉट में असाइन किया गया है.
शैडो डीओएम इवेंट मॉडल
जब कोई इवेंट शैडो डीओएम से बबल अप होता है, तो उसके टारगेट को अडजस्ट किया जाता है, ताकि शैडो डीओएम से मिलने वाले एनकैप्सुलेशन को बनाए रखा जा सके. इसका मतलब है कि इवेंट को फिर से टारगेट किया जाता है, ताकि ऐसा लगे कि वे आपके शैडो DOM के अंदर मौजूद एलिमेंट के बजाय, कॉम्पोनेंट से आए हैं. कुछ इवेंट, शैडो डीओएम से बाहर भी नहीं फैलते.
शैडो बाउंड्री को पार करने वाले इवेंट ये हैं:
- फ़ोकस इवेंट:
blur,focus,focusin,focusout - माउस इवेंट:
click,dblclick,mousedown,mouseenter,mousemoveवगैरह. - व्हील इवेंट:
wheel - इनपुट इवेंट:
beforeinput,input - कीबोर्ड इवेंट:
keydown,keyup - कंपोज़िशन इवेंट:
compositionstart,compositionupdate,compositionend - DragEvent:
dragstart,drag,dragend,dropवगैरह.
सलाह
अगर शैडो ट्री खुला है, तो event.composedPath() को कॉल करने पर, उन नोड का कलेक्शन दिखेगा जिनसे होकर इवेंट गुज़रा है.
कस्टम इवेंट का इस्तेमाल करना
शैडो ट्री में इंटरनल नोड पर ट्रिगर होने वाले कस्टम डीओएम इवेंट, शैडो बाउंड्री से बाहर नहीं जाते. हालांकि, अगर इवेंट को 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 है. इससे शैडो ट्री में मौजूद एलिमेंट के फ़ोकस करने के तरीके को बेहतर बनाया जा सकता है:
- अगर शैडो डीओएम में मौजूद किसी नोड पर क्लिक किया जाता है और वह नोड फ़ोकस करने लायक नहीं है, तो फ़ोकस करने लायक पहला नोड फ़ोकस हो जाता है.
- जब शैडो DOM के अंदर मौजूद किसी नोड पर फ़ोकस किया जाता है, तो फ़ोकस किए गए एलिमेंट के साथ-साथ होस्ट पर भी
: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> पर फ़ोकस किया गया है.
delegatesFocus: false और <x-focus>
पर फ़ोकस किया जाता है (उदाहरण के लिए, इसमें tabindex="0" है).
delegatesFocus: false और "क्लिक किए जा सकने वाले शैडो डीओएम टेक्स्ट" पर
क्लिक किया जाता है (या एलिमेंट के शैडो डीओएम में मौजूद किसी अन्य खाली जगह पर क्लिक किया जाता है).
सुझाव और तरकीबें
मैंने पिछले कुछ सालों में वेब कॉम्पोनेंट बनाने के बारे में काफ़ी कुछ सीखा है. हमें लगता है कि कॉम्पोनेंट बनाने और शैडो डीओएम को डीबग करने के लिए, आपको इनमें से कुछ सलाह काम की लगेंगी.
सीएसएस कंटेनमेंट का इस्तेमाल करना
आम तौर पर, वेब कॉम्पोनेंट का लेआउट/स्टाइल/पेंट अपने-आप में पूरा होता है. परफ़ॉर्मेंस को बेहतर बनाने के लिए, :host में सीएसएस कंटेनमेंट का इस्तेमाल करें:
<style>
:host {
display: block;
contain: content; /* Boom. CSS containment FTW. */
}
</style>
इनहेरिट की जा सकने वाली स्टाइल रीसेट करना
इनहेरिट की जा सकने वाली स्टाइल (background, color, font, line-height वगैरह) शैडो डीओएम में इनहेरिट होती रहती हैं. इसका मतलब है कि वे डिफ़ॉल्ट रूप से शैडो डीओएम की सीमा को पार कर जाते हैं. अगर आपको नए सिरे से शुरुआत करनी है, तो शैडो बाउंड्री को पार करने पर, इनहेरिट की जा सकने वाली स्टाइल को उनकी शुरुआती वैल्यू पर रीसेट करने के लिए, 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>
किसी पेज पर इस्तेमाल किए गए सभी कस्टम एलिमेंट ढूंढना
कभी-कभी, पेज पर इस्तेमाल किए गए कस्टम एलिमेंट ढूंढना फ़ायदेमंद होता है. ऐसा करने के लिए, आपको पेज पर इस्तेमाल किए गए सभी एलिमेंट के शैडो DOM को बार-बार ट्रैवर्स करना होगा.
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 कुछ समय से शैडो डीओएम का पुराना वर्शन उपलब्ध करा रहे हैं. Blink, कुछ समय तक दोनों वर्शन के साथ काम करता रहेगा. v0 स्पेसिफ़िकेशन में शैडो रूट बनाने का एक अलग तरीका दिया गया था (v1 के element.attachShadow के बजाय element.createShadowRoot). पुराने तरीके को कॉल करने से, v0 सिमैंटिक के साथ शैडो रूट बनता रहता है. इसलिए, मौजूदा v0 कोड काम करना बंद नहीं करेगा.
अगर आपको v0 के पुराने वर्शन में दिलचस्पी है, तो html5rocks के लेख देखें: 1, 2, 3. शैडो डीओएम v0 और v1 के बीच के अंतर की भी बेहतरीन तुलना की गई है.
ब्राउज़र समर्थन
शैडो डीओएम v1, Chrome 53 (स्टेटस), Opera 40, Safari 10, और Firefox 63 में उपलब्ध है. Edge ने डेवलपमेंट शुरू कर दिया है.
शैडो DOM की सुविधा का पता लगाने के लिए, देखें कि attachShadow मौजूद है या नहीं:
const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;
Polyfill
जब तक ब्राउज़र पर यह सुविधा बड़े पैमाने पर उपलब्ध नहीं हो जाती, तब तक shadydom और shadycss पॉलीफ़िल आपको v1 की सुविधा देते हैं. Shady DOM, Shadow DOM और shadycss polyfills के DOM स्कोपिंग की नकल करता है. साथ ही, यह सीएसएस की कस्टम प्रॉपर्टी और नेटिव एपीआई से मिलने वाले स्टाइल स्कोपिंग की भी नकल करता है.
पॉलीफ़िल इंस्टॉल करें:
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 देखें.
नतीजा
पहली बार, हमारे पास एक ऐसा एपीआई प्रिमिटिव है जो सीएसएस स्कोपिंग और डीओएम स्कोपिंग को सही तरीके से करता है. साथ ही, इसमें सही कंपोज़िशन है. कस्टम एलिमेंट जैसे अन्य वेब कॉम्पोनेंट एपीआई के साथ मिलकर, शैडो डीओएम, कॉम्पोनेंट को पूरी तरह से एन्कैप्सुलेट करने का तरीका उपलब्ध कराता है. इसके लिए, हैक या <iframe>s जैसे पुराने तरीकों का इस्तेमाल करने की ज़रूरत नहीं होती.
मुझे गलत मत समझो. शैडो डीओएम वाकई एक मुश्किल चीज़ है! लेकिन यह एक ऐसा दानव है जिसके बारे में जानना ज़रूरी है. इसे थोड़ा समय दें. इसके बारे में जानें और सवाल पूछें!
इस बारे में और पढ़ें
- शैडो डीओएम v1 और v0 के बीच अंतर
- WebKit ब्लॉग से "Introducing Slot-Based Shadow DOM API".
- वेब कॉम्पोनेंट और मॉड्यूलर सीएसएस का भविष्य फ़िलिप वॉल्टन ने लिखा है
- Google के WebFundamentals से "कस्टम एलिमेंट: फिर से इस्तेमाल किए जा सकने वाले वेब कॉम्पोनेंट बनाना".
- शैडो डीओएम v1 की खास जानकारी
- कस्टम एलिमेंट v1 की खास जानकारी
अक्सर पूछे जाने वाले सवाल
क्या शैडो डीओएम v1 का इस्तेमाल आज किया जा सकता है?
हां, पॉलीफ़िल की मदद से. ब्राउज़र से जुड़ी सहायता देखें.
शैडो डीओएम में सुरक्षा से जुड़ी कौनसी सुविधाएं मिलती हैं?
शैडो डीओएम, सुरक्षा से जुड़ी सुविधा नहीं है. यह सीएसएस को स्कोप करने और कॉम्पोनेंट में डीओएम ट्री को छिपाने के लिए, एक हल्का टूल है. अगर आपको सुरक्षा की बेहतर सुविधा चाहिए, तो <iframe> का इस्तेमाल करें.
क्या किसी वेब कॉम्पोनेंट के लिए शैडो डीओएम का इस्तेमाल करना ज़रूरी है?
नहीं! आपको शैडो डीओएम का इस्तेमाल करने वाले वेब कॉम्पोनेंट बनाने की ज़रूरत नहीं है. हालांकि, शैडो डीओएम का इस्तेमाल करने वाले कस्टम एलिमेंट बनाने का मतलब है कि आपको सीएसएस स्कोपिंग, डीओएम एनकैप्सुलेशन, और कंपोज़िशन जैसी सुविधाओं का फ़ायदा मिल सकता है.
ओपन और क्लोज़्ड शैडो रूट में क्या अंतर है?
क्लोज़्ड शैडो रूट देखें.