0Pricing
JavaScript Academy · درس

نمط تفويض الأحداث

تعاملوا مع أحداث العديد من العناصر الفرعية من خلال مستمع واحد في العنصر الأصل.

نمط تفويض الأحداث درس مجاني في JavaScript Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في JavaScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة JavaScript Academy 4 دروس في المجموع.

مستمع واحد يحكمها جميعًا

يعني تفويض الأحداث إرفاق مستمع واحد بسلف مشترك بدلًا من إرفاق مستمعين كثيرين بالعناصر الابنة الفردية. وبما أن الأحداث تنتشر صعودًا، يستقبل العنصر الأب نقرات جميع العناصر المنحدرة منه.

<ul id="menu">
  <li>Home</li>
  <li>About</li>
  <li>Contact</li>
</ul>

النهج الساذج

من دون التفويض، ستكرر على كل عنصر وتُرفق به معالجًا. هذا يهدر الموارد: إذ يستهلك ذاكرة أكبر، كما أنه لا يعمل مع العناصر المضافة لاحقًا.

document.querySelectorAll("#menu li").forEach((li) => {
  li.addEventListener("click", () => console.log(li.textContent));
});

النهج المعتمد على التفويض

بدلًا من ذلك، أرفق مستمعًا واحدًا بالعنصر الأب وافحص event.target لمعرفة العنصر الابن الذي نُقر عليه.

const menu = document.getElementById("menu");
menu.addEventListener("click", (e) => {
  console.log(e.target.textContent);
});

مطابقة الهدف الصحيح

قد تقع النقرة على عنصر متداخل. استخدم event.target.closest(selector) للصعود عبر العناصر والعثور على السلف ذي الصلة الذي يطابق المحدد.

menu.addEventListener("click", (e) => {
  const item = e.target.closest("li");
  if (!item) return; // clicked outside any li
  console.log("Clicked:", item.textContent);
});

الحماية باستخدام فحص

احرص دائمًا على التعامل مع النقرات التي لا تطابق المطلوب. يمنع الخروج المبكر if (!item) return; معالجك من التعطل عندما ينقر المستخدم على مساحة داخلية أو فجوة داخل الحاوية.

menu.addEventListener("click", (e) => {
  const item = e.target.closest("li");
  if (!item || !menu.contains(item)) return;
  handleSelect(item);
});

استخدام سمات البيانات

من الأنماط الشائعة تخزين معرّف أو إجراء لكل عنصر باستخدام سمة data-*. يقرأ المعالج المفوَّض هذه القيمة من العنصر المطابق.

menu.addEventListener("click", (e) => {
  const item = e.target.closest("li");
  if (!item) return;
  const id = item.dataset.id;   // reads data-id
  console.log("Selected id:", id);
});

توجيه التنفيذ حسب الإجراء

بالنسبة إلى أشرطة الأدوات التي تحتوي على أزرار كثيرة، امنح كل زر سمة data-action واستخدمها في عبارة switch. يتولى مستمع واحد معالجة جميع الأزرار.

toolbar.addEventListener("click", (e) => {
  const btn = e.target.closest("button");
  if (!btn) return;
  switch (btn.dataset.action) {
    case "save": save(); break;
    case "delete": remove(); break;
  }
});

لماذا يتوسع هذا الأسلوب جيدًا

باستخدام التفويض، تحتاج قائمة تضم 1000 صف إلى مستمع واحد فقط بدلًا من 1000 مستمع. وهذا يعني ذاكرة أقل، وإعدادًا أسرع، وعدم الحاجة إلى حلقة تنظيف عند تغير الصفوف.

ملاحظة حول الأداء

للتفويض تكلفة صغيرة فعلًا: إذ يشغّل كل حدث مطابق معالجك، ثم يتولى المعالج تصفيته. بالنسبة إلى معظم التطبيقات، تكون هذه التكلفة ضئيلة مقارنةً بالتوفير، لكن تجنب إرفاق مستمعات مفوَّضة بالعنصر document للأحداث شديدة التكرار مثل mousemove.

اختيار الحاوية

اختر أقرب سلف مستقر يحتوي على جميع الأهداف. ويُعد التفويض إلى حاوية محددة (القائمة نفسها) أفضل من التفويض إلى document، لأن عدد الأحداث غير المرتبطة التي تشغّل معالجك يكون أقل.

const list = document.querySelector(".task-list");
list.addEventListener("click", onTaskClick);

الدمج مع closest

تُعد closest() جوهر التفويض. فهي تعيد العنصر نفسه إذا كان يطابق المحدد، أو أقرب سلف مطابق، أو null. وهذا يجعل التفويض آمنًا عند التعامل مع ترميز متداخل.

const cell = e.target.closest("td[data-col]");
if (cell) console.log(cell.dataset.col);

تحقق سريع

لماذا نستخدم تفويض الأحداث؟

مراجعة

يرفق تفويض الأحداث مستمعًا واحدًا بالعنصر الأب، ويستخدم الانتشار صعودًا لمعالجة جميع العناصر الابنة. استخدم e.target.closest(selector) للعثور على العنصر ذي الصلة، واحمِ المعالج بخروج مبكر، واقرأ سمات data-* لتوجيه الإجراءات. يتوسع هذا الأسلوب جيدًا مع القوائم الضخمة، وهو النمط القياسي لواجهات المستخدم الديناميكية.

الأسئلة الشائعة

هل درس «نمط تفويض الأحداث» مجاني؟

نعم — نص درس «نمط تفويض الأحداث» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة JavaScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة JavaScript Academy 4 دروس في المجموع.

ماذا ستتعلم في «نمط تفويض الأحداث»؟

تعاملوا مع أحداث العديد من العناصر الفرعية من خلال مستمع واحد في العنصر الأصل. تتمرن على JavaScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ JavaScript Academy؟

لا تُشترط خبرة سابقة. JavaScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «نمط تفويض الأحداث»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس JavaScript Academy هذا؟

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

جميع الدروس في هذه الدورة

  1. مرحلتا الالتقاط والانتشار
  2. نمط تفويض الأحداث
  3. القوائم الديناميكية مع التفويض
  4. الأحداث المخصصة
← العودة إلى JavaScript Academy