শ্যাডো রুট হল হোস্ট এলিমেন্টের সাথে অ্যাটাচ করা এনক্যাপসুলেট করা DOM সাবট্রি: এর মধ্যে থাকা স্টাইল বাইরে লিক করে না এবং পৃষ্ঠার স্টাইল ভিতরে লিক করে না (উত্তরাধিকার সূত্রে প্রাপ্ত প্রপার্টি ছাড়া)। টেমপ্লেট দক্ষতার সাথে ট্রি তৈরি করে; স্লট এতে Light DOM কন্টেন্ট প্রজেক্ট করে।
শ্যাডো রুট অ্যাটাচ করা হচ্ছে
this.attachShadow({ mode: 'open', delegatesFocus: true });
delegatesFocus: true হোস্টকে ফোকাস করার মাধ্যমে শ্যাডো ট্রির মধ্যে প্রথম ফোকাসযোগ্য এলিমেন্টে ফোকাস সরায়, হোস্টের জন্য :focus স্টাইলিং রুট করে এবং ফর্ম-সম্পর্কিত কাস্টম এলিমেন্টে (static formAssociated = true) ইনার কন্ট্রোলে <label> ক্লিক ফরওয়ার্ড করে। কম্পোনেন্ট ফোকাস করা যায় এমন কন্ট্রোল র্যাপ করলে এটি সেট করুন। প্রায় সব ক্ষেত্রেই mode: 'open' ব্যবহার করুন যাতে ডেভ টুল, পৃষ্ঠা স্ক্রিপ্ট ও সার্ভার হাইড্রেশন element.shadowRoot-এ পৌঁছাতে পারে (ওয়েব কম্পোনেন্ট ওরিয়েন্টেশন দেখুন)।
টেমপ্লেট: দক্ষতার সাথে ট্রি তৈরি করো
<template> একবার (মডিউল স্কোপ বা স্ট্যাটিক ফিল্ড) ডিফাইন করুন এবং প্রতিটি ইনস্ট্যান্সের জন্য এটি ক্লোন করুন। প্রতিটি কনস্ট্রাকশনে innerHTML স্ট্রিং আবার পার্স করার চেয়ে পার্স করা ফ্র্যাগমেন্ট ক্লোন করা অনেক দ্রুত হয়।
const template = document.createElement('template');
template.innerHTML = `
<div class="card">
<slot name="header"></slot>
<div class="body"><slot></slot></div>
<slot name="footer"></slot>
</div>
`;
class MyCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
// MANDATORY: deep-clone the template content so each instance gets its own nodes.
this.shadowRoot.append(template.content.cloneNode(true));
}
}
customElements.define('my-card', MyCard);
টেমপ্লেট ছোট রাখুন। গভীরভাবে নেস্ট করা "div soup" এবং নেস্ট করা শ্যাডো রুটের অনেক লেভেল, পরিমাপযোগ্য স্টাইল-রেজোলিউশন এবং লেআউট খরচ, উভয়ই যোগ করে, যা স্কেলে একটি বড় পারফর্ম্যান্স হিট। ফ্ল্যাট স্ট্রাকচার ও সিম্যান্টিক এলিমেন্ট পছন্দ করুন।
স্লট: যে অংশগুলি মানুষকে অবাক করে
ডিফল্ট বনাম নামযুক্ত স্লট ডকুমেন্ট অনুযায়ী কাজ করে; এগুলি হল সেইসব আচরণ যা কামড়ায়:
- হোয়াইটস্পেস গণনা করা হয়। এলিমেন্টের মধ্যে টেক্সট নোড (শুধু হোয়াইটস্পেস সহ) ডিফল্ট স্লটে অ্যাসাইন করা হয়, তাই ডিফল্ট স্লট খুব কমই "ফাঁকা" থাকে।
- DOM অর্ডার বজায় রাখা হয়, স্লট অর্ডার নয়। প্রজেক্ট করা নোডগুলি
:first-child/:last-childউদ্দেশ্যে তাদের আসল লাইট DOM অর্ডার রাখে, তারা কোন স্লট পূরণ করে তা নির্বিশেষে।::slotted(*:first-child)নিয়ম প্রথম DOM চাইল্ডকে টার্গেট করে, সেই স্লটের প্রথম চাইল্ডকে নয়, তাই এটি প্রায়ই আপনার প্রত্যাশার সাথে মিলবে না। slotchangeহল আপগ্রেড-টাইমিং সিগন্যাল। অ্যাসাইন করা নোড পরিবর্তন হলে (প্রাথমিক অ্যাসাইনমেন্ট সহ) এটি ফায়ার হয় এবং আপগ্রেডের পরে লাইট DOM চাইল্ড এসেছে কিনা তা জানার নির্ভরযোগ্য উপায়, যখনconnectedCallback-এর সময় সেগুলি নাও থাকতে পারে।
this.shadowRoot.querySelector('slot[name="header"]')
.addEventListener('slotchange', (e) => {
const nodes = e.target.assignedElements();
this.toggleAttribute('has-header', nodes.length > 0);
});
শ্যাডো রুটে স্টাইলশিট লোড করা হচ্ছে
| পদ্ধতি | সুবিধা | অসুবিধা |
|---|---|---|
টেমপ্লেটে <style> |
সহজ, সম্পূর্ণ এনক্যাপসুলেট করা, JS ছাড়াই কাজ করে। | প্রতিটি ইনস্ট্যান্সের জন্য ডুপ্লিকেট করা হয়েছে; DOM-এর সাইজ অনেক বাড়িয়ে দেয়। |
<link rel="stylesheet"> |
ক্যাশে করা যায় এমন এক্সটার্নাল ফাইল। | অতিরিক্ত অনুরোধ; স্টাইল না করা কন্টেন্ট ফ্ল্যাশ করার ঝুঁকি। |
adoptedStyleSheets |
সব ইনস্ট্যান্স জুড়ে একটি শেয়ার করা CSSStyleSheet; স্কেলে সবচেয়ে দ্রুত। |
JS প্রয়োজন; তৈরি করা শিটে @import কাজ করে না। |
একটি কম্পোনেন্টের অনেক ইনস্ট্যান্সের জন্য, শেয়ার করা কনস্ট্রাক্টেড স্টাইলশিট ব্যবহার করা ভালো:
const sheet = new CSSStyleSheet();
sheet.replaceSync(`:host { display: block; }`);
class MyCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
// The same sheet object is reused by every instance; no per-instance parse.
this.shadowRoot.adoptedStyleSheets = [sheet];
}
}