أتقن دورة حياة العنصر المخصّص، وتغليف Shadow DOM، وإسقاط المحتوى عبر الفتحات (slots).
افتح هذا الدرس في Kodokonتوسّع العناصر المخصّصة (custom elements) مفردات HTML: يمكن تسجيل أي صنف يرث من HTMLElement في CustomElementRegistry، ما دام اسمه يحتوي على شرطة (user-badge، وليس userbadge أبدًا). نقطة دقيقة: إذا ظهر الوسم في المستند قبل استدعاء customElements.define، فإنه يُنشأ أولًا كعنصر مجهول ثم يُرقّى في مكانه - عندئذ يُستدعى المُنشئ لاحقًا على عقدة موجودة سلفًا في الشجرة.
class UserBadge extends HTMLElement {
static observedAttributes = ["name"];
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
this.textContent = this.getAttribute("name");
}
}
customElements.define("user-badge", UserBadge);تخفي دورة الحياة بعض المصائد: لا يُطلَق attributeChangedCallback إلا للسمات المدرجة في observedAttributes، وأثناء الترقية يُستدعى لكل سمة موجودة سلفًا قبل connectedCallback. تمنع المواصفة المُنشئ من فحص السمات والأبناء، أو من إضافة أي منها: في لحظة تشغيله (عبر createElement أو الاستنساخ)، قد يكون العنصر فارغًا تمامًا.
<template id="card-tpl">
<style>
:host { display: block; padding: 1rem; }
::slotted(h2) { margin: 0; }
</style>
<slot name="title"></slot>
<slot></slot>
</template>ينشئ attachShadow شجرة فرعية مغلّفة: لا تتسرّب الأنماط منها، ولا تصل إليها محدِّدات الصفحة - فقط خصائص CSS الموروثة (color، font) والخصائص المخصّصة تعبر الحدّ. يعيش محتوى <template> في DocumentFragment يمكن الوصول إليه عبر .content: لا تعمل نصوصه البرمجية ولا تُحمَّل صوره حتى تستنسخه في المستند. تُسقَط العُقد الموضوعة في الـ light DOM في عناصر <slot>: تبقى فيزيائيًا في الـ light DOM، ويُخطرك الحدث slotchange بأي تغيير في الإسناد.
class InfoCard extends HTMLElement {
constructor() {
super();
const tpl = document.getElementById("card-tpl");
this.attachShadow({ mode: "open" })
.appendChild(tpl.content.cloneNode(true));
}
}
customElements.define("info-card", InfoCard);يستحق امتدادان انتباهك. العناصر المخصّصة المرتبطة بالنماذج: مع static formAssociated = true وattachInternals()، يشارك مكوّنك في النماذج مشاركة كاملة (القيمة المُرسَلة، التحقق الأصلي، حالات :invalid). والـ Shadow DOM التصريحي: <template shadowrootmode=open> يُرفق جذرًا ظليًا وقت التحليل، دون JavaScript، ما يجعل مكوّنات الويب متوافقة مع التصيير من جهة الخادم.
attachShadow({ mode: 'closed' })، ماذا يعيد element.shadowRoot من الخارج؟null: فقط المرجع الذي يعيده attachShadow يتيح الوصول إلى الجذر الظلّي<slot>؟