ข้ามไปเนื้อหาหลัก

Event Delegation — ผูก listener ครั้งเดียวกับ parent

แทนที่จะผูก event listener กับทุก element ให้ผูกครั้งเดียวกับ parent แล้วใช้ event.target เลือก element ที่คลิก — ลด memory และรองรับ dynamic elements อัตโนมัติ

// แบบไม่ดี — N listeners สำหรับ N items
document.querySelectorAll('.btn-delete').forEach((btn) => {
  btn.addEventListener('click', handleDelete);
});

// แบบดี — 1 listener บน parent
document.querySelector('#list').addEventListener('click', (event) => {
  const btn = event.target.closest('.btn-delete');
  if (!btn) return;           // คลิกที่อื่น — ไม่ทำอะไร

  const id = btn.dataset.id;
  handleDelete(id);
});

closest() เดิน DOM ขึ้นไปหา ancestor ที่ match selector — สำคัญเมื่อ button มี icon ข้างใน แล้ว event.target อาจเป็น <svg> ไม่ใช่ <button>

กรณีที่ดีที่สุดสำหรับ delegation:

  • List item ที่เพิ่ม/ลบ dynamically (innerHTML หรือ framework)
  • Table row ที่มี action buttons หลาย column
  • Virtual scroll ที่ re-render DOM