跳到主要内容

Event Delegation

Event delegation = listen on parent, handle on child


What is Event Delegation?

"Listen on parent, handle child events"

Event delegation attaches an event listener to a parent element instead of individual child elements.

"Event delegation attaches event listeners to a parent element, using event bubbling to handle events from child elements."


How It Works

Event bubbling enables delegation

// Listen on parent
document.getElementById("list").addEventListener("click", (e) => {
// Check if clicked element is a list item
if (e.target.tagName === "LI") {
console.log("List item clicked:", e.target.textContent);
}
});

Events bubble up from child to parent.

"Event delegation works because events bubble up from child to parent, allowing the parent to handle child events."


Benefits

Performance · Dynamic content · Memory

  • Performance: One listener instead of many
  • Dynamic content: Works with added elements
  • Memory: Fewer event listeners
  • Simpler: Less code to manage

"Event delegation improves performance with fewer listeners, works with dynamically added elements, and uses less memory."


Example: List Items

One listener for all items

// ❌ Without delegation - listener per item
items.forEach((item) => {
item.addEventListener("click", handleClick);
});

// ✅ With delegation - one listener
list.addEventListener("click", (e) => {
if (e.target.matches("li")) {
handleClick(e.target);
}
});

"Event delegation uses one listener on the parent instead of multiple listeners on each child."


Dynamic Content

Works with elements added later

// Listener on parent
list.addEventListener("click", handleClick);

// Add new item later - still works!
const newItem = document.createElement("li");
newItem.textContent = "New Item";
list.appendChild(newItem);

"Event delegation automatically works with dynamically added elements without adding new listeners."


Event Target

e.target = actual clicked element

parent.addEventListener("click", (e) => {
console.log(e.target); // The actual clicked element
console.log(e.currentTarget); // The parent (listener)
});

"e.target is the element that triggered the event, e.currentTarget is the element with the listener."


Matching Elements

Check e.target with matches() or tagName

parent.addEventListener("click", (e) => {
// Check tag name
if (e.target.tagName === "BUTTON") {
// Handle button click
}

// Check class
if (e.target.matches(".button")) {
// Handle button click
}

// Check closest parent
const button = e.target.closest(".button");
if (button) {
// Handle button click
}
});

"Use e.target.tagName, e.target.matches(), or e.target.closest() to identify which child was clicked."


When to Use

Many elements · Dynamic content

Use event delegation when:

  • Many similar elements
  • Dynamically added elements
  • Performance is important
  • Elements share common parent

"Use event delegation for lists, tables, or any scenario with many similar elements or dynamic content."


9️⃣ When NOT to Use

Simple cases · Need event.stopPropagation()

Don't use when:

  • Very few elements
  • Need to stop propagation
  • Complex event handling per element

"Avoid event delegation for simple cases with few elements or when you need to stop event propagation."


React Event Delegation

React uses delegation automatically

React automatically uses event delegation - all events are delegated to the document root.

"React automatically uses event delegation, attaching listeners to the document root and handling events through synthetic events."


"Event delegation attaches listeners to parent elements instead of children, using event bubbling. It improves performance with fewer listeners, works with dynamic content, and uses less memory. Use e.target to identify the clicked element and matches() or closest() to filter. React uses event delegation automatically."


🧠 Ultra-Short Cheat Sheet

Listen on parent, handle children
Event bubbling
e.target = clicked element
Performance benefit
Works with dynamic content
matches() / closest() to filter