صفحه اصلی >> بلاگ >> استفاده از Shadow DOM

استفاده از Shadow DOM

دسته:html تاریخ انتشار: 12 فوریه 2021 ایمان رضایی

یکی از جنبه های مهم اجزای وب ، کپسوله سازی است - این امکان وجود دارد که ساختار نشانه گذاری ، سبک و رفتار را از سایر کدهای صفحه پنهان و جدا نگه دارید تا قسمت های مختلف با هم تداخل نداشته باشند و کد را به خوبی و تمیز نگه دارید. Shadow DOM API بخش اصلی این امر است ، و راهی برای اتصال DOM جداگانه مخفی به یک عنصر فراهم می کند. این مقاله اصول استفاده از Shadow DOM را پوشش می دهد.

توجه: Shadow DOM به طور پیش فرض در Firefox (63 به بعد) ، Chrome ، Opera و Safari پشتیبانی می شود. Edge جدید مبتنی بر Chromium (75 به بعد) نیز از آن پشتیبانی می کند. Edge قدیمی از آن پشتیبانی نمی کرد.

 

 

نمای سطح بالا

این مقاله فرض می کند که شما قبلاً با مفهوم DOM (Document Object Model) آشنا هستید - یک ساختار درخت مانند از گره های متصل که نمایانگر عناصر و رشته های مختلف متن است که در یک سند نشانه گذاری ظاهر می شوند (معمولاً یک سند HTML در مورد اسناد وب) به عنوان مثال ، قطعه HTML زیر را در نظر بگیرید:

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8">

    <title>Simple DOM example</title>

  </head>

  <body>

      <section>

        <img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">

        <p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p>

      </section>

  </body>

</html>

این قطعه ساختار DOM زیر را تولید می کند:

 

Shadow DOM اجازه می دهد تا درختان پنهان DOM به عناصر موجود در درخت معمولی DOM متصل شوند - این درخت سایه دار DOM با یک ریشه سایه شروع می شود ، در زیر آن می توان به هر عنصر دیگری که می خواهید متصل شود ، به همان روشی که DOM معمولی است.

برخی از اصطلاحات DOM shadow وجود دارد که باید از آنها آگاه باشید:

  • Shadow host: گره DOM معمولی که سایه DOM به آن متصل است.
  • Shadow tree: درخت DOM درون سایه DOM.
  • Shadow boundary: مکانی که DOM سایه به پایان می رسد و DOM معمولی آغاز می شود.
  • Shadow root: گره ریشه درخت سایه.

 

شما می توانید گره های موجود در DOM سایه را دقیقاً به همان شیوه گره های غیر سایه تحت تأثیر قرار دهید - به عنوان مثال ضمیمه کردن فرزندان یا تنظیم ویژگی ها ، حالت دهی به گره های جداگانه با استفاده از element.style.foo یا افزودن سبک به کل درخت DOM سایه در داخل یک   <style> عنصر. تفاوت در این است که هیچ یک از کدهای داخل DOM سایه ای نمی تواند بر روی هر چیزی خارج از آن تأثیر بگذارد ، و به این ترتیب امکان کپسوله سازی مفید وجود دارد.

توجه داشته باشید که DOM سایه به هیچ وجه چیز جدیدی نیست - مرورگرها مدت طولانی است که از آن برای کپسول سازی ساختار داخلی یک عنصر استفاده می کنند. به عنوان مثال به یک عنصر  <video> فکر کنید ، در حالی که کنترلهای پیش فرض مرورگر در معرض آن است. آنچه در DOM مشاهده می کنید عنصر  <video> است ، اما شامل یک سری دکمه ها و سایر کنترل ها در داخل DOM سایه خود است. مشخصات سایه DOM آن را طوری ساخته است که به شما اجازه می دهد در واقع سایه DOM عناصر سفارشی خود را دستکاری کنید.

 

کاربرد اساسی

با استفاده از روش  ()Element.attachShadow  می توانید به هر عنصری یک ریشه سایه وصل کنید. این به عنوان پارامتر یک شی گزینه ای است که شامل یک گزینه  — mode — با مقدار open یا close است:

let shadow = elementRef.attachShadow({mode: 'open'});
let shadow = elementRef.attachShadow({mode: 'closed'});

open به این معنی است که می توانید با استفاده از جاوا اسکریپت که در متن صفحه اصلی نوشته شده است ، به عنوان مثال با استفاده از ویژگی  Element.shadowRoot به سایه DOM دسترسی پیدا کنید:

let myShadowDom = myCustomElem.shadowRoot;

اگر یک ریشه سایه را به یک عنصر سفارشی با  mode: closed وصل کنید ، از خارج نمی توانید به سایه DOM دسترسی پیدا کنید -  myCustomElem.shadowRoot   null را برمی گرداند. این مورد در مورد عناصر داخلی شامل DOM های سایه مانند <video>. وجود دارد.

اگر شما به عنوان بخشی از سازنده آن ، یک DOM سایه را به یک عنصر سفارشی متصل می کنید (مفیدترین کاربرد DOM سایه) ، از موارد زیر استفاده می کنید:

let shadow = this.attachShadow({mode: 'open'});

هنگامی که یک DOM سایه را به عنصری متصل کردید ، دستکاری در آن فقط با استفاده از API های همان  DOM امکان پذیر است که برای دستکاری منظم DOM استفاده می کنید:

let para = document.createElement('p');
shadow.appendChild(para);
// etc.

یک مثال ساده

حال بیایید با یک مثال ساده سایه DOM را در داخل یک عنصر سفارشی نشان دهیم - <popup-info> (به یک مثال زنده نیز مراجعه کنید). این یک آیکون تصویر و یک رشته متن را می گیرد و آیکون را در صفحه جاسازی می کند. وقتی نماد متمرکز است ، متن را در یک جعبه اطلاعات پاپ آپ نمایش می دهد تا اطلاعات بیشتری در متن ارائه دهد. برای شروع ، در پرونده جاوا اسکریپت ما یک کلاس به نام PopUpInfo تعریف می کنیم ، که HTMLElement را گسترش می دهد:

class PopUpInfo extends HTMLElement {
  constructor() {
    // Always call super first in constructor
    super();

 
    // write element functionality in here

 
    ...
  }
}

در داخل تعریف کلاس ، سازنده عنصر را تعریف می کنیم ، که تمام کارایی عنصر را هنگام نمونه سازی آن تعریف می کند.

ایجاد ریشه سایه

ابتدا یک ریشه سایه به عنصر سفارشی وصل می کنیم:

// Create a shadow root
let shadow = this.attachShadow({mode: 'open'});

ایجاد ساختار shadow DOM

بعد ، ما از برخی دستکاری های DOM برای ایجاد ساختار DOM سایه داخلی عنصر استفاده می کنیم:

// Create spans
let wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
let icon = document.createElement('span');
icon.setAttribute('class', 'icon');
icon.setAttribute('tabindex', 0);
let info = document.createElement('span');
info.setAttribute('class', 'info');

 
// Take attribute content and put it inside the info span
let text = this.getAttribute('data-text');
info.textContent = text;

 
// Insert icon
let imgUrl;
if(this.hasAttribute('img')) {
  imgUrl = this.getAttribute('img');
} else {
  imgUrl = 'img/default.png';
}
let img = document.createElement('img');
img.src = imgUrl;
icon.appendChild(img);

طراحی ظاهر shadow DOM

بعد از آن ما یک عنصر  <style> ایجاد می کنیم و آن را با مقداری CSS پر می کنیم تا ظاهر آن بهتر شود:

// Create some CSS to apply to the shadow dom
let style = document.createElement('style');

 
style.textContent = `
.wrapper {
  position: relative;
}

 
.info {
  font-size: 0.8rem;
  width: 200px;
  display: inline-block;
  border: 1px solid black;
  padding: 10px;
  background: white;
  border-radius: 10px;
  opacity: 0;
  transition: 0.6s all;
  position: absolute;
  bottom: 20px;
  left: 10px;
  z-index: 3;
}

 
img {
  width: 1.2rem;
}

 
.icon:hover + .info, .icon:focus + .info {
  opacity: 1;
}`;

اتصال shadow DOM به shdow root

مرحله آخر اتصال تمام عناصر ایجاد شده به ریشه سایه است:

// attach the created elements to the shadow dom
shadow.appendChild(style);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);

با استفاده از عنصر سفارشی ما

پس از تعریف کلاس ، استفاده از عنصر به همان سادگی تعریف و قرار دادن آن در صفحه است ، همانطور که در استفاده از عناصر سفارشی توضیح داده شده است:

// Define the new element
customElements.define('popup-info', PopUpInfo);

 

<popup-info img="img/alt.png" data-text="Your card validation code (CVC) is an extra 
security feature — it is the last 3 or 4
numbers on the back of your card.">

سبک های داخلی درمقابل خارجی

در مثال فوق ما با استفاده از عنصر  <style> سبک را به Shadow DOM اعمال می کنیم ، اما انجام این کار با ارجاع یک صفحه سبک خارجی از یک عنصر  <link> کاملاً امکان پذیر است.

به عنوان مثال ، از مثال popup-info-box-external-stylesheet  ما به این کد نگاهی بیندازید (کد منبع را ببینید):

// Apply external styles to the shadow dom
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');

 
// Attach the created element to the shadow dom
shadow.appendChild(linkElem);

توجه داشته باشید که عناصر  <link> رنگ ریشه سایه را مسدود نمی کنند ، بنابراین ممکن است در هنگام بارگیری صفحه محتوای بدون استایل وجود داشته باشد.

بسیاری از مرورگرهای مدرن بهینه سازی را برای برچسب های  <style> یا از یک گره مشترک شبیه سازی شده یا دارای متن یکسان انجام می دهند ، به آنها امکان می دهد یک فایل استایل پشتیبان را به اشتراک بگذارند. با استفاده از این بهینه سازی ، عملکرد استایل های خارجی و داخلی باید یکسان باشد.


n0
n40

برای ثبت نظر باید وارد سایت شوید یا ثبت نام نمایید.


نظر شما با موفقیت در سیستم ثبت گردید.