در اکوسیستم مدرن فرانتاند، تکیه بر فریمورکهای خاصی مانند React، Vue یا Angular رایج است. با این حال، نیاز به کامپوننتهای رابط کاربری که از این مرزها فراتر بروند، رو به افزایش است. چه در حال نگهداری از یک برنامه jQuery قدیمی باشید، چه در حال ساخت یک معماری میکرو-فرانتاند، یا صرفاً بخواهید اطمینان حاصل کنید که سیستم طراحی شما قابل حمل باقی بماند، وب کامپوننتها یک راهحل بومی و مبتنی بر استاندارد ارائه میدهند. این راهنما بررسی میکند که چگونه میتوان یک مجموعه رابط کاربری قوی و مستقل از فریمورک را با استفاده از عناصر سفارشی و Shadow DOM ساخت.
فلسفه اصلی: کپسولهسازی و قابلیت همکاری
وب کامپوننتها راهحل جادویی برای همه مشکلات نیستند، اما در ایجاد قطعات ایزوله و قابل استفاده مجدد رابط کاربری عالی عمل میکنند. این فناوری بر سه ستون اصلی تکیه دارد: عناصر سفارشی (Custom Elements) که به شما امکان تعریف تگهای HTML جدید را میدهند؛ Shadow DOM که استایلدهی و کپسولهسازی نشانهگذاری را در محدوده مشخص فراهم میکند؛ و قالبهای HTML که دستکاری کارآمد DOM را امکانپذیر میسازند.
با بهرهگیری از این APIها، میتوانید کامپوننتهایی ایجاد کنید که ظاهر و رفتار یکسانی در مرورگرها و فریمورکهای مختلف داشته باشند، بدون اینکه با هزینه اضافی ناشی از مقایسه (diffing) DOM مجازی یا هوکهای چرخه عمر خاص فریمورک مواجه شوید.
مرحله ۱: تعریف عنصر سفارشی
پایه و اساس هر وب کامپوننت، کلاس عنصر سفارشی است. این کلاس از HTMLElement ارثبری کرده و رفتار، چرخه عمر و ویژگیهای کامپوننت را تعریف میکند. بیایید با ساخت یک کامپوننت ساده و قابل استفاده مجدد به نام app-button شروع کنیم.
class AppButton extends HTMLElement {
constructor() {
super();
// اتصال ریشه سایه برای کپسولهسازی
this.attachShadow({ mode: 'open' });
this.render();
}
// واکنش به تغییرات ویژگیها
static get observedAttributes() {
return ['variant', 'disabled'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.render();
}
}
// رندر کردن DOM داخلی کامپوننت
render() {
const variant = this.getAttribute('variant') || 'primary';
const disabled = this.hasAttribute('disabled');
this.shadowRoot.innerHTML = `
`;
}
}
// ثبت کامپوننت
customElements.define('app-button', AppButton);
در این مثال، ما از static get observedAttributes() استفاده میکنیم تا به مرورگر بگوییم کدام ویژگیها باید باعث رندر مجدد شوند. متد attributeChangedCallback تضمین میکند که رابط کاربری ما با ویژگیهای HTML ارسالی به کامپوننت همگام باقی بماند.
مرحله ۲: تسلط بر Shadow DOM و استایلدهی
Shadow DOM جایی است که جادوی کپسولهسازی رخ میدهد. استایلهایی که در داخل :host یا در درخت سایه تعریف میشوند، نشت نمیکنند و استایلهای خارجی نیز در آن اختلال ایجاد نمیکنند. این موضوع برای مجموعههای رابط کاربری حیاتی است زیرا از تداخل CSS در برنامههای بزرگ جلوگیری میکند.
با این حال، ممکن است نیاز داشته باشید که به مصرفکنندگان مجموعه رابط کاربری خود اجازه دهید بخشهای خاصی را استایلدهی کنند. اینجاست که عنصر <slot> وارد عمل میشود. در کد بالا، ما از <slot> داخل دکمه استفاده کردیم تا به کاربران اجازه دهیم محتوای سفارشی مانند آیکونها یا متن را وارد کنند، در حالی که ساختار دکمه دستنخورده باقی میماند.
مرحله ۳: مدیریت رویدادها در محیط ایزوله
یکی از اشتباهات رایج مبتدیان، مدیریت رویدادها در داخل Shadow DOM است. رویدادهایی که از درخت سایه منشأ میشوند (مانند کلیک روی یک دکمه)، مگر اینکه ترکیبپذیر (composed) باشند، به طور خودکار در DOM سبک (کامپوننت والد) قابل دسترسی نیستند. شما میتوانید این رفتار را با تنظیم پرچم composed: true روی رویدادهای سفارشی خود کنترل کنید.
handleClick() {
this.dispatchEvent(new CustomEvent('click', {
bubbles: true,
composed: true, // اجازه خروج رویداد از Shadow DOM
detail: { action: 'submit' }
}));
}
با تنظیم composed: true، اطمینان حاصل میکنید که برنامه والد میتواند به رویدادهای پرتاب شده توسط کامپوننت شما گوش دهد و قابلیت همکاری حفظ شود.
نتیجهگیری
ساخت یک مجموعه رابط کاربری مستقل از فریمورک با استفاده از وب کامپوننتها، یک سرمایهگذاری استراتژیک برای نگهداری بلندمدت است. این کار وابستگیها را کاهش میدهد، آزمایش را ساده میکند و تضمین میکند که سیستم طراحی شما برای آینده ایمن باقی میماند. اگرچه منحنی یادگیری شامل درک مرزهای کپسولهسازی است، اما پاداش آن مجموعهای از اصول اولیه رابط کاربری بسیار قابل حمل، با عملکرد بالا و یکسان است. با یک کامپوننت واحد شروع کنید، با Shadow DOM آزمایش کنید و به تدریج مجموعه خود را برای پوشش کل سیستم طراحیتان گسترش دهید.