The Personal Blog of Todd Sharp

Better Performance With Event Delegation In Vue

Posted By: Todd Sharp on 9/28/2017 1:11 UTC
Tagged: VueJS

The last few days I've been going through the Vue.js documentation to learn a little more about the framework.  I'm impressed in its simplistic, concise approach to front-end dev and even more impressed with their obvious attention to performance with the framework.  However, one item jumped out at me when going through the documentation that reminded me of another article that I'd read recently so I thought I'd share a simple refactor to one of their examples that could make a world of difference in the performance of larger Single Page Applications.

Here's the standard"todo" application as shown in their documentation.  It's a good example because it shows a few concepts in action:  components, event handling, binding, looping - all things that are building blocks to Vue (or really any) application.

Pretty straightforward, but notice how we're attaching an event handler on every single <li>inside of the v-for loop?  That's how I've always done things without even a second thought until I read this article about event delegation.  It makes total sense when you think about it - all events in the DOM "bubble" up to the window element.  So why have tens (or hundreds, or thousands) of event handlers when a single event handler on a common parent element can handle everything with a bit of logic?  To quote the SitePoint article:

Event delegation makes use of two often overlooked features of JavaScript events: event bubbling and the target element. When an event is triggered on an element, for example a mouse click on a button, the same event is also triggered on all of that element’s ancestors. This process is known as event bubbling; the event bubbles up from the originating element to the top of the DOM tree. The target element of any event is the originating element, the button in our example, and is stored in a property of the event object. Using event delegation it’s possible to add an event handler to an element, wait for an event to bubble up from a child element and easily determine from which element the event originated.

So how can we refactor the todo list to take advantage of a single event handler instead of having a handler on every element in the loop?  Like so:

So what has changed here?  First we removed the v-on:click from the <li> inside our component.  Next we added a click handler to our <ul> that wraps the todo list and pointed it at a new removeTodo() method that simply checks that the target element is a button (more complex logic could be necessary) and if so we find the index of our list element and remove it.  A simple refactor, but you can imagine the performance benefits in larger applications.