في النظام البيئي الحديث للواجهة الأمامية، يعتمد الكثيرون على أطر عمل محددة مثل React أو Vue أو Angular. ومع ذلك، هناك حاجة متزايدة لمكونات واجهة المستخدم تتجاوز هذه الحدود. سواء كنت تحافظ على تطبيق jQuery قديم، أو تبني بنية الواجهات الأمامية المصغرة، أو ببساطة تريد ضمان قابلية نقل نظام التصميم الخاص بك، فإن مكونات الويب تقدم حلاً أصلياً قائماً على المعايير. يستكشف هذا الدليل كيفية بناء مجموعة واجهة مستخدم قوية وغير مرتبطة بإطار عمل باستخدام العناصر المخصصة والظل DOM.
الفلسفة الأساسية: التغليف والتشغيل المتبادل
مكونات الويب ليست حلاً سحرياً لكل المشاكل، لكنها تتفوق في إنشاء أجزاء واجهة مستخدم معزولة وقابلة لإعادة الاستخدام. تعتمد هذه التقنية على ثلاثة أعمدة رئيسية: العناصر المخصصة، التي تتيح لك تعريف وسوم HTML جديدة؛ والظل DOM، الذي يوفر تنسيقاً محدداً وتغليفاً للعلامات؛ وقوالب HTML، التي تتيح معالجة DOM بكفاءة.
من خلال الاستفادة من واجهات برمجة التطبيقات هذه، يمكنك إنشاء مكونات تبدو وتتصرف بشكل متسق عبر المتصفحات وأطر العمل المختلفة دون الحاجة إلى عبء مقارنة شجرة DOM الافتراضية أو خطوط حياة محددة لإطار العمل.
الخطوة 1: تعريف العنصر المخصص
أساس أي مكون ويب هو فئة العنصر المخصص. تمتد هذه الفئة من 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 الممررة إلى المكون.
الخطوة 2: إتقان الظل DOM والتنسيق
يحدث سحر التغليف داخل الظل DOM. لا تتسرب الأنماط المعرفة داخل :host أو داخل شجرة الظل إلى الخارج، ولا تتداخل الأنماط الخارجية معها. هذا أمر بالغ الأهمية لمجموعات واجهة المستخدم لأنه يمنع تعارضات CSS في التطبيقات الأكبر حجماً.
ومع ذلك، قد تحتاج إلى السماح لمستهلكي مجموعة واجهة المستخدم الخاصة بك بتنسيق أجزاء محددة. هنا يأتي دور عنصر <slot>. في الكود أعلاه، استخدمنا <slot> داخل الزر للسماح للمستخدمين بتمرير محتوى مخصص، مثل الأيقونات أو النص، مع الحفاظ على هيكل الزر سليماً.
الخطوة 3: معالجة الأحداث في بيئة معزولة
أحد الأخطاء الشائعة للمبتدئين هو معالجة الأحداث داخل الظل DOM. الأحداث التي تنشأ داخل شجرة الظل (مثل النقر على زر) لا تكون متاحة تلقائياً في DOM الخفيف (المكون الأب) ما لم يتم تركيبها. يمكنك التحكم في هذا السلوك عن طريق تعيين علم composed: true على أحداثك المخصصة.
handleClick() {
this.dispatchEvent(new CustomEvent('click', {
bubbles: true,
composed: true, // يسمح للخروج من ظل DOM
detail: { action: 'submit' }
}));
}
من خلال تعيين composed: true، تضمن أن التطبيق الأب يمكنه الاستماع للأحداث التي يطلقها مكونك، مما يحافظ على التشغيل المتبادل.
الخاتمة
بناء مجموعة واجهة مستخدم غير مرتبطة بإطار عمل باستخدام مكونات الويب هو استثمار استراتيجي في قابلية الصيانة طويلة المدى. إنه يقلل من الترابط، ويبسط الاختبار، ويضمن بقاء نظام التصميم الخاص بك مستقبلياً. بينما تتضمن منحنى التعلم فهم حدود التغليف، فإن العائد هو مجموعة من البدائل الأساسية لواجهة المستخدم عالية القابلية للنقل والأداء والاتساق. ابدأ صغيراً بمكون واحد، وتجربة الظل DOM، وقم بتوسيع مجموعتك تدريجياً لتغطية نظام التصميم بأكمله.