تسمح العناصر المخصّصة لمطوّري الويب بتحديد علامات HTML جديدة وتوسيع نطاق العلامات الحالية وإنشاء مكونات ويب قابلة لإعادة الاستخدام.
باستخدام العناصر المخصّصة، يمكن لمطوّري الويب إنشاء علامات HTML جديدة، أو تعزيز علامات HTML الحالية، أو توسيع المكونات التي أنشأها مطوّرون آخرون. واجهة برمجة التطبيقات هي الأساس لمكوّنات الويب. وتوفّر هذه الطريقة المتوافقة مع معايير الويب لإنشاء مكوّنات قابلة لإعادة الاستخدام باستخدام لغة برمجة JavaScript/HTML/CSS عادية. والنتيجة هي استخدام رموز أقل ورمز وحدات وإعادة استخدام أكبر في تطبيقاتنا.
مقدمة
يوفّر لنا المتصفّح أداة ممتازة لتنظيم تطبيقات الويب. يُعرف باسم HTML. ربما سمعت عن ذلك. وهي لغة برمجة تعريفية وقابلة للنقل ومدعومة بشكل جيد وسهلة الاستخدام. على الرغم من أنّ لغة HTML رائعة، إلا أنّ مفرداتها وإمكانية توسيع نطاقها محدودة. لم يكن المعيار المتغيّر لـ HTML يتضمّن دائمًا طريقة لربط سلوك JavaScript تلقائيًا بعلامات الترميز، إلى أن تم توفير هذه الطريقة الآن.
العناصر المخصّصة هي الحلّ لتعديل رمز HTML وملء الأجزاء التي تنقصك وربط البنية بالسلوك. إذا لم يقدّم رمز HTML حلّاً لمشكلة معيّنة، يمكننا إنشاء عنصر مخصّص يقدّم حلّاً لها. تُعلِّم العناصر المخصّصة المتصفّح حيلًا جديدة مع الحفاظ على مزايا HTML.
تحديد عنصر جديد
لتعريف عنصر HTML جديد، نحتاج إلى إمكانات JavaScript.
يتم استخدام العنصر الشامل customElements لتحديد عنصر مخصّص وإعلام المتصفّح بعلامة جديدة. استخدِم customElements.define() مع اسم العلامة
التي تريد إنشاؤها وclass JavaScript الذي يمدّد القاعدة HTMLElement.
مثال: تحديد لوحة أدراج على الأجهزة الجوّالة، <app-drawer>:
class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);
// Or use an anonymous class if you don't want a named constructor in current scope.
window.customElements.define('app-drawer', class extends HTMLElement {...});
مثال على الاستخدام:
<app-drawer></app-drawer>
من المهم تذكُّر أنّ استخدام عنصر مخصّص لا يختلف عن استخدام <div> أو أي عنصر آخر. يمكن الإعلان عن النماذج على الصفحة،
وإنشاؤها ديناميكيًا في JavaScript، ويمكن إرفاق مستمعي الأحداث، وما إلى ذلك. يمكنك متابعة قراءة هذه المقالة للاطّلاع على مزيد من الأمثلة.
تحديد واجهة برمجة تطبيقات JavaScript للعنصر
يتم تحديد وظيفة العنصر المخصّص باستخدام ES2015
class
الذي يمتد إلى HTMLElement. يضمن تمديد HTMLElement أن يرث العنصر المخصّص
واجهة برمجة التطبيقات DOM API بالكامل، ويعني ذلك أنّ أيّ سمات أو طرق تضيفها إلى HTMLElementتصبح جزءًا من واجهة DOM للعنصر. في الأساس، استخدِم الفئة ل
إنشاء واجهة برمجة تطبيقات JavaScript عامة لعلامتك.
مثال: تحديد واجهة DOM لعنصر <app-drawer>:
class AppDrawer extends HTMLElement {
// A getter/setter for an open property.
get open() {
return this.hasAttribute('open');
}
set open(val) {
// Reflect the value of the open property as an HTML attribute.
if (val) {
this.setAttribute('open', '');
} else {
this.removeAttribute('open');
}
this.toggleDrawer();
}
// A getter/setter for a disabled property.
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of the disabled property as an HTML attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Can define constructor arguments if you wish.
constructor() {
// If you define a constructor, always call super() first!
// This is specific to CE and required by the spec.
super();
// Setup a click listener on <app-drawer> itself.
this.addEventListener('click', e => {
// Don't toggle the drawer if it's disabled.
if (this.disabled) {
return;
}
this.toggleDrawer();
});
}
toggleDrawer() {
// ...
}
}
customElements.define('app-drawer', AppDrawer);
في هذا المثال، سننشئ درجًا يتضمّن السمة open والسمة disabled
وطريقة toggleDrawer(). ويعرض أيضًا السمات على أنّها سمات HTML.
من الميزات الرائعة للعناصر المخصّصة أنّ this داخل تعريف فئة
يشير إلى عنصر DOM نفسه، أي مثيل الفئة. في مثالنا، يشير this إلى <app-drawer>. (😉) هذه هي الطريقة التي يمكن للعنصر من خلالها
إرفاق مستمع click بنفسه. ولا تقتصر على أدوات معالجة الأحداث.
تتوفّر واجهة برمجة التطبيقات DOM API بالكامل داخل رمز العنصر. استخدِم this للوصول إلى
سمات العنصر، وفحص عناصره الفرعية (this.children)، وعقد الاستعلامات
(this.querySelectorAll('.items'))، وما إلى ذلك.
قواعد إنشاء عناصر مخصّصة
- يجب أن يحتوي اسم العنصر المخصّص على واصلة (-). وبالتالي، فإنّ
<x-tags>و<my-element>و<my-awesome-app>هي أسماء صالحة، في حين أنّ<tabs>و<foo_bar>غير صالحَين. ويُستخدَم هذا الشرط لكي يتمكّن منظِّم HTML من التمييز بين العناصر المخصّصة والعناصر العادية. ويضمن أيضًا التوافق مع الإصدارات القادمة عند إضافة علامات جديدة إلى HTML. - لا يمكنك تسجيل العلامة نفسها أكثر من مرّة. سيؤدي محاولة إجراء ذلك إلى
ظهور
DOMException. بعد إبلاغ المتصفّح بعلامة جديدة، لن تحتاج إلى مزيد من الخطوات. لا يمكن إرجاع المنتجات. - لا يمكن أن تكون العناصر المخصّصة ذات إغلاق ذاتي لأنّ HTML لا يسمح إلا ببضعة
عناصر
بإغلاق ذاتي. اكتب دائمًا علامة إغلاق
(
<app-drawer></app-drawer>).
تفاعلات العناصر المخصّصة
يمكن للعنصر المخصّص تحديد أدوات ربط خاصة بالدورة التدريبية لتشغيل الرمز البرمجي أثناء الأوقات المهمة من وجوده. وتُعرف هذه التفاعلات باسم تفاعلات العناصر المخصّصة.
| الاسم | يتم استدعاؤه عند |
|---|---|
constructor |
يتم
إنشاء مثيل للعنصر أو ترقيته. وهي مفيدة لإعداد
الحالة أو إعداد أدوات معالجة الأحداث أو
إنشاء عنصر shadow dom.
يمكنك الاطّلاع على
المواصفات
لمعرفة القيود المفروضة على الإجراءات التي يمكنك اتّخاذها في constructor.
|
connectedCallback |
يتمّ استدعاؤها كلّ مرّة يتمّ فيها إدخال عنصر في DOM. وهي مفيدة لتشغيل رمز الإعداد، مثل جلب الموارد أو المعالجة. بشكل عام، يجب محاولة تأخير العمل إلى هذا الوقت. |
disconnectedCallback |
يتمّ استدعاؤه في كلّ مرّة تتمّ فيها إزالة العنصر من DOM. مفيد لتشغيل رمز برمجي لتنظيف الملفات. |
attributeChangedCallback(attrName, oldVal, newVal) |
يتمّ استدعاؤه عند
إضافة سمة تمّ رصدها أو إزالتها أو تعديلها أو استبدالها. يتمّ استدعاء هذه الوظيفة أيضًا للقيم الأوّلية
عند إنشاء عنصر من قِبل المُحلِّل أو
ترقيته. ملاحظة: لن تتلقّى سوى
السمات المدرَجة في السمة observedAttributes
هذا المرجع إلى دالة.
|
adoptedCallback |
تم نقل العنصر المخصّص
إلى document جديد (مثل
شخص يُدعى document.adoptNode(el)).
|
تكون عمليات استدعاء التفاعلات متزامنة. إذا اتصل أحد الأشخاص بـ el.setAttribute()
في العنصر، سيتصل المتصفّح بـ attributeChangedCallback() على الفور.
وبالمثل، ستتلقّى disconnectedCallback() مباشرةً بعد إزالة العنصر
من DOM (على سبيل المثال، يُطلِق المستخدم el.remove()).
مثال: إضافة تفاعلات عناصر مخصّصة إلى <app-drawer>:
class AppDrawer extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// ...
}
connectedCallback() {
// ...
}
disconnectedCallback() {
// ...
}
attributeChangedCallback(attrName, oldVal, newVal) {
// ...
}
}
حدِّد التفاعلات إذا كان ذلك منطقيًا. إذا كان العنصر معقّدًا بما يكفي
ويفتح اتصالاً بقاعدة بيانات IndexedDB في connectedCallback()، عليك تنفيذ عملية التنظيف اللازمة
في disconnectedCallback(). يُرجى توخّي الحذر. لا يمكنك الاعتماد على إزالة
العنصر من DOM في جميع الحالات. على سبيل المثال، لن يتم استدعاء disconnectedCallback() مطلقًا إذا أغلق المستخدم علامة التبويب.
السمات والخصائص
ربط السمات بالخصائص
من الشائع أن تعكس سمات HTML قيمتها في عنصر DOM كسمة
HTML. على سبيل المثال، عند تغيير قيم hidden أو id في
JS:
div.id = 'my-id';
div.hidden = true;
يتم تطبيق القيم على ملف DOM المباشر كسمات:
<div id="my-id" hidden>
ويُعرف ذلك باسم عرض السمات على الخصائص. تُجري كل المواقع تقريبًا في HTML ذلك. لماذا؟ تكون السمات مفيدة أيضًا ل ضبط عنصر بشكل تعريفي، وتعتمد بعض واجهات برمجة التطبيقات، مثل أدوات اختيار CSS وأدوات تسهيل الاستخدام، على السمات للعمل.
يكون عرض السمة مفيدًا في أيّ مكان تريد فيه مزامنة تمثيل نموذج العناصر في المستند (DOM) مع حالة JavaScript. من بين الأسباب التي قد تدفعك إلى عكس خاصية هو تطبيق التصميم الذي يحدّده المستخدم عند تغيير حالة JavaScript.
نذكّرك بأنّنا تواصلنا معك في <app-drawer>. قد يريد مستهلك هذا المكوّن إخفاءه تدريجيًا
و/أو منع تفاعل المستخدم معه عندما يكون غير مفعّل:
app-drawer[disabled] {
opacity: 0.5;
pointer-events: none;
}
عند تغيير السمة disabled في JavaScript، نريد أن تتم
إضافة هذه السمة إلى DOM حتى يتطابق مع عنصر اختيار المستخدم. يمكن أن يقدّم العنصر هذا السلوك
من خلال عرض القيمة لسمة تحمل الاسم نفسه:
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of `disabled` as an attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
this.toggleDrawer();
}
مراقبة التغييرات في السمات
سمات HTML هي طريقة ملائمة للمستخدمين لتحديد الحالة الأولية:
<app-drawer open disabled></app-drawer>
يمكن للعناصر التفاعل مع تغييرات السمات من خلال تحديد
attributeChangedCallback. سيستدعي المتصفّح هذه الطريقة عند كل تغيير
في السمات المدرَجة في صفيف observedAttributes.
class AppDrawer extends HTMLElement {
// ...
static get observedAttributes() {
return ['disabled', 'open'];
}
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Only called for the disabled and open attributes due to observedAttributes
attributeChangedCallback(name, oldValue, newValue) {
// When the drawer is disabled, update keyboard/screen reader behavior.
if (