تقنيات الويب 3 دقائق للقراءة

دليل لتطوير مكونات ويب قابلة للتطوير باستخدام Shadow DOM والعناصر المخصصة والفتحات

PROFSCODE Ekibi 10 يوليو 2026
Paylaş:
تطوير واجهة مستخدم معيارية وقابلة لإعادة الاستخدام باستخدام مكونات الويب

في تطبيقات الويب الحديثة، تعد إدارة مكونات واجهة المستخدم وإعادة استخدامها تحديًا مستمرًا للمطورين. بينما توفر أطر عمل JavaScript حلولًا، فإن مشاركة المكونات عبر أطر عمل مختلفة أو بشكل مستقل تمامًا غالبًا ما يكون صعبًا. هنا يأتي دور مكونات الويب. تتيح لنا هذه المجموعة من المعايير المدعومة محليًا من قبل المتصفحات إنشاء مكونات واجهة مستخدم معيارية حقًا ومغلفة ومستقلة عن أي إطار عمل.

العناصر المخصصة (Custom Elements): أنشئ علامات HTML الخاصة بك

تسمح لك العناصر المخصصة، التي تشكل أساس مكونات الويب، بتعريف علامات HTML الخاصة بك. يتيح لك ذلك إنشاء علامات ذات معنى خاصة بمشروعك (مثل <my-card>) بدلاً من العلامات الموجودة مثل <button> أو <div>. لإنشاء عنصر مخصص، تقوم بتوسيع فئة <code>HTMLElement</code> وتسجيلها باستخدام طريقة <code>customElements.define()</code>.


class MyCard extends HTMLElement {
  constructor() {
    super(); // Always call super() first in constructor
    this.innerHTML = `
      <style>
        .card {
          border: 1px solid #ccc;
          padding: 16px;
          border-radius: 8px;
          box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
        }
        h3 {
          color: #333;
        }
      </style>
      <div class="card">
        <h3>عنوان</h3>
        <p>هذا مكون بطاقة.</p>
      </div>
    `;
  }
}

customElements.define('my-card', MyCard);

بعد إضافة هذا الكود إلى ملف HTML الخاص بك، يمكنك استخدام المكون الخاص بك في صفحتك باستخدام العلامة <code><my-card></my-card></code>.

Shadow DOM: التغليف بعزل المكونات

العناصر المخصصة هي الخطوة الأولى لإنشاء مكون. ومع ذلك، لمنع تعارضات الأنماط والسلوك، نحتاج إلى التغليف. هذا هو المكان الذي يأتي فيه Shadow DOM. ينشئ Shadow DOM شجرة DOM مخفية تعزل الهيكل الداخلي لمكونك وأنماطه عن المستند الرئيسي. وبالتالي، فإن قواعد CSS داخل مكونك لا تتسرب إلى الخارج، ولا تؤثر قواعد CSS الخارجية على الأجزاء الداخلية لمكونك.


class MyShadowCard extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' }); // Attach a shadow root
    shadowRoot.innerHTML = `
      <style>
        .card {
          border: 1px solid #007bff; /* Different border color */
          padding: 20px;
          border-radius: 10px;
          box-shadow: 3px 3px 10px rgba(0,123,255,0.2);
          font-family: Arial, sans-serif;
          background-color: #e9f5ff;
        }
        h3 {
          color: #0056b3;
          margin-top: 0;
        }
        p {
          color: #444;
          line-height: 1.6;
        }
      </style>
      <div class="card">
        <h3>بطاقة Shadow DOM</h3>
        <p>أنماط هذه البطاقة مغلفة بالكامل باستخدام Shadow DOM.</p>
      </div>
    `;
  }
}

customElements.define('my-shadow-card', MyShadowCard);

الآن، عندما تستخدم <code><my-shadow-card></my-shadow-card></code>، سترى أن قواعد الأنماط الداخلية تعمل بشكل مستقل عن بقية الصفحة. تعني <code>mode: 'open'</code> أنه يمكنك الوصول إلى Shadow DOM باستخدام JavaScript؛ في وضع <code>'closed'</code>، لا يمكن الوصول.

الفتحات (Slots): توزيع المحتوى الديناميكي

ولكن ماذا لو أردنا إدراج محتوى ديناميكي في مكوننا من الخارج؟ على سبيل المثال، إذا كان عنوان البطاقة أو محتواها سيختلف في كل استخدام؟ هذا هو المكان الذي يأتي فيه عنصر HTML <code><slot></code>. تسمح لك الفتحات بوضع المحتوى القادم من خارج Shadow DOM في نقاط محددة داخل شجرة الظل لمكونك.


class MySlottedCard extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = `
      <style>
        .card {
          border: 1px dashed #28a745; /* Different border style */
          padding: 15px;
          margin-bottom: 10px;
          border-radius: 5px;
          background-color: #f0fff4;
        }
        ::slotted(h3) { /* Styling content passed through slots */
          color: #218838;
          font-size: 1.5em;
        }
        ::slotted(p) {
          color: #333;
        }
      </style>
      <div class="card">
        <slot name="card-title"><h3>عنوان افتراضي</h3></slot>
        <slot><p>محتوى افتراضي.</p></slot>
        <footer><small>تم البناء باستخدام مكون الويب.</small></footer>
      </div>
    `;
  }
}

customElements.define('my-slotted-card', MySlottedCard);

عند استخدام هذا المكون، يمكنك وضع المحتوى وفقًا لأسماء الفتحات:


<my-slotted-card>
  <h3 slot="card-title">عنوان بطاقة مخصص</h3>
  <p>محتوى هذه البطاقة يأتي من الخارج.</p>
  <p>بفضل الفتحات، لدينا هيكل مرن.</p>
</my-slotted-card>

<my-slotted-card>
  <h3 slot="card-title">عنوان مختلف</h3>
  <p>يمكن استخدامه مع فقرة واحدة فقط.</p>
</my-slotted-card>

<my-slotted-card>
  <!-- استخدم المحتوى الافتراضي فقط -->
</my-slotted-card>

يمكن تسمية علامات <code><slot></code> باستخدام خاصية <code>name</code>. تلتقط <code><slot></code> غير المسماة (الفتحة الافتراضية) كل المحتوى غير المخصص للفتحات المسماة. يمكنك أيضًا إضافة محتوى افتراضي داخل <code><slot></code> لتحديد ما سيتم عرضه عندما لا يتم توفير أي شيء من الخارج.

الاستخدام المتقدم وأفضل الممارسات

  • دوال رد النداء الخاصة بدورة الحياة (Lifecycle Callbacks): تمتلك العناصر المخصصة دوال رد نداء خاصة بدورة الحياة. على سبيل المثال، يتم تشغيل <code>connectedCallback()</code> عند إضافة المكون إلى DOM، ويتم تشغيل <code>disconnectedCallback()</code> عند إزالته. مثال:
    
    class MyLifecycleElement extends HTMLElement {
      connectedCallback() {
        console.log('تمت إضافة المكون إلى DOM.');
        // يمكن إضافة مستمعي الأحداث هنا.
      }
    
      disconnectedCallback() {
        console.log('تمت إزالة المكون من DOM.');
        // يمكن تنظيف مستمعي الأحداث هنا.
      }
    }
    customElements.define('my-lifecycle-element', MyLifecycleElement);
    
  • السمات مقابل الخصائص (Attributes vs. Properties): سمات HTML هي قيم نصية وتنعكس في DOM. يمكن أن تكون خصائص JavaScript من أي نوع ويتم الاحتفاظ بها مباشرة على كائن العنصر. للاستماع إلى تغييرات السمات، يمكنك استخدام <code>static get observedAttributes()</code> وطرق <code>attributeChangedCallback(name, oldValue, newValue)</code>.
  • تنسيق مكونات الويب (Styling Web Components): الأنماط داخل Shadow DOM مغلفة ولا يمكن الوصول إليها مباشرة من الخارج. ومع ذلك، يمكن استخدام محددات CSS <code>::part()</code> لتنسيق عناصر داخلية محددة من الخارج. يمكنك أيضًا تمرير معلمات الأنماط من خارج المكون باستخدام <code>خصائص CSS المخصصة (متغيرات CSS)</code>.

الخاتمة

توفر مكونات الويب، مع العناصر المخصصة و Shadow DOM والفتحات، معيارًا قويًا في تطوير الويب الحديث. بفضل التغليف وقابلية إعادة الاستخدام والاستقلال عن الإطار، فإنها تمكنك من بناء تطبيقات ويب أكثر استدامة وأداءً وقابلية للتشغيل المتبادل. خاصة في المشاريع الكبيرة أو المواقف التي تحتاج فيها مشاريع متعددة إلى استخدام نفس مكونات واجهة المستخدم، تصبح مكونات الويب أداة لا غنى عنها. سيعمل تعلم هذه التقنية على نقل بنية الواجهة الأمامية الخاصة بك إلى المستوى التالي.

العودة إلى المدونة

التعليقات (0)

لا توجد تعليقات بعد. كن أول من يعلق!

إرسال التعليق