Event Delegation: A Technique to Improve JavaScript Performance

Published: 8 months ago - Updated: 8 months ago

3 minutes - 585 Words

article 'Event Delegation: A Technique to Improve JavaScript Performance' banner

Summary

In this blog post, you will learn what event delegation is, how it can help you optimize your JavaScript code by reducing the number of event listeners, and how to implement it with a practical example.

Introduction

Let’s start with an example. Suppose we have a navigation menu with several links, and we want to implement a smooth scrolling effect when the user clicks on any of the links.

<nav class="nav">
  <ul class="nav__links">

    <li class="nav__item">
      <a class="nav__link" href="#about">About</a>
    </li>

    <li class="nav__item">
      <a class="nav__link" href="#projects">Projects</a>
    </li>

    <li class="nav__item">
      <a class="nav__link" href="#testimonials">Testimonials</a>
    </li>

  </ul>
</nav>

A bad approach

A naive approach would be to loop over all the links and add a click event listener to each one of them, like this:

document.querySelectorAll('.nav__link').forEach(function(el) {
    el.addEventListener('click', function(e) {
        e.preventDefault();

        const id = this.getAttribute('href');

        document.querySelector(id).scrollIntoView({
            behavior: 'smooth'
        });
    });
});

This works, but it has a problem: we are adding as many event listeners as there are links, which can affect the performance and memory usage of our web page. Imagine if we have hundreds or thousands of links, that would be a lot of unnecessary event listeners!

How can we solve this problem? The answer is event delegation.

A better approach

Event delegation is a technique that allows us to attach a single event listener to a common parent element, and then use the event object to determine which child element triggered the event. This way, we can handle multiple events with a single event listener, and avoid adding too many event listeners to the DOM.

To implement event delegation, we need to do two things:

  1. Add a single event listener to the common parent element. In our case, that would be the element with the class nav__links.
  2. Use the event object to check which child element originated the event. In our case, we only want to handle the events that come from the elements with the class nav__link.

Here is how our code would look like with event delegation:

document.querySelector('.nav__links').addEventListener('click', function(e) {
    e.preventDefault();
 
    if (!e.target.classList.contains('nav__link')) return

    const id = e.target.getAttribute('href');

    document.querySelector(id).scrollIntoView({
        behavior: 'smooth'
    });
});
  • The event can be triggered by any child element or the parent element itself.

  • We are only interested in the events that come from the elements with the class nav__link

  • Matching strategy: we use the classList property of the event target to check if it contains the class nav__link

    The matching strategy is the most important part here, make sure to adjust it to your own code.
    For example if one of our nav__link has more that one child, the above matching strategy wont work.

     <a class="nav__link" href="#section--3">
        <span>[Child]</span>
        Testimonials
     </a>
    

    In these cases the JavaScript selector closest() comes very handy

      // ...
    
      const navLinkEl = e.target.closest('.nav__link');
     
      const id = navLinkEl.getAttribute('href');
    
      // ....
    

As you can see, we have reduced the number of event listeners from N (the number of links) to 1 (the parent element). This improves the performance and memory usage of our web page, and also makes our code more maintainable and scalable.

Conclusion

Event delegation is a powerful technique that can help us optimize our JavaScript code and handle multiple events with a single event listener. It is based on the concept of event bubbling, which means that an event that occurs on a child element will propagate up to its parent elements until it reaches the document object. By using event delegation, we can take advantage of this behavior and handle events at a higher level in the DOM hierarchy.

I hope you enjoyed this blog post and learned something new about event delegation. If you have any questions or feedback, please leave a comment below. Thank you for reading!

Add Comment

Conversations (1)

coreycorey

Nice overview. But you may want to mention that special handling is required if those anchor tags had a span or other child element in them that was clicked on. `event.target` would reference that span or child node instead of the anchor node.

shahryarshahryar

Great point, thank you for reminding me. I will update the article and add an example for it.

Sign up for our newsletter

Stay up to date with the latest news and articles.