Event Delegation
Capturing and bubbling allow us to implement one of the most powerful event-handling patterns called event delegation. Event delegation is a technique in JavaScript that allows you to add a single event listener to a parent element, rather than adding event listeners to multiple child elements. This can be useful when you have a large number of elements that need to handle the same event, as it can reduce the amount of code you need to write and improve the performance of your application.
How it's done
Here's an example of how event delegation works:
we have a ul
element with three li
elements inside it. We've added a single-click event listener to the ul
element. When any of the li
elements are clicked, the event bubbles up to the ul
element and is handled by the event listener.
Using event delegation, we can handle events for multiple elements with a single event listener, rather than having to add an event listener to each element individually. This can be more efficient and easier to maintain.
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
document.getElementById('list').addEventListener('click', function(event) {
// Check if the clicked element is a list item
if (event.target.tagName === 'LI') {
// Do something with the list item
console.log('You clicked on a list item!');
}
});
A Real Example
Let’s say, we want to make a menu with buttons “Save”, “Load”, “Search” and so on. And there’s an object with methods save
, load
, search
… How to match them?
The first idea may be to assign a separate handler to each button. But there’s a more elegant solution. We can add a handler for the whole menu and data-action
attributes for button that has the method to call:
<div id="menu">
<button data-action="save">Save</button>
<button data-action="load">Load</button>
<button data-action="search">Search</button>
</div>
class Menu {
constructor(elem) {
this._elem = elem;
elem.onclick = this.onClick.bind(this); // (*)
}
save() {
alert('saving');
}
load() {
alert('loading');
}
search() {
alert('searching');
}
onClick(event) {
let action = event.target.dataset.action;
if (action) {
this[action]();
}
};
}
new Menu(menu);
Use Cases
Event delegation can be useful in a number of situations when working with JavaScript:
When you have a large number of elements that need to handle the same event: Instead of adding an event listener to each element individually, you can use event delegation to handle the event for all of the elements at once.
When you need to add event listeners to elements that are dynamically added to the page: If you add an event listener to an element that doesn't exist yet, it won't work. With event delegation, you can add the event listener to a parent element that does exist, and it will work for any child elements that are added later.
When you want to improve the performance of your application: Adding a large number of event listeners can impact the performance of your application, especially if the listeners are attached to elements that are high up in the DOM tree. By using event delegation, you can reduce the number of event listeners you need to add, which can improve the performance of your application.
When you want to simplify the code for your application: Event delegation allows you to add a single event listener to a parent element, rather than adding multiple event listeners to child elements. This can make your code easier to read and maintain.
Limitations
Event delegation only works for events that bubble up the DOM tree: Not all events bubble up the DOM tree. For example, the
focus
andblur
events do not bubble. If you want to use event delegation with these types of events, you'll need to use a different technique, such as attaching the event listener to the document object.Event delegation can make it harder to debug events: When you use event delegation, the event listener is attached to a parent element, rather than the element that actually generated the event. This can make it harder to determine which element caused the event to be triggered, as the
event.target
property will refer to the parent element, rather than the element that was actually clicked.Event delegation can be confusing for beginners: Event delegation can be a bit confusing for developers who are new to JavaScript, as it involves adding event listeners to parent elements rather than the elements themselves. It can take some time to get used to this concept and understand how it works.
Event delegation may not be the best choice for every situation: While event delegation can be a useful technique in some cases, it's not always the best choice. For example, if you only have a few elements that need to handle the same event, it may be simpler to just add event listeners to each element individually.
Summary
Event delegation allows you to add a single event listener to a parent element, rather than adding event listeners to multiple child elements.
It’s often used to add the same handling for many similar elements, but not only for that.
The algorithm:
Put a single handler on the container.
In the handler – check the source element
event.target
.If the event happened inside an element that interests us, then handle the event.
Useful Links:
https://javascript.info/event-delegation
https://www.geeksforgeeks.org/event-delegation-in-javascript/
https://www.freecodecamp.org/news/event-delegation-javascript/
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events