简体   繁体   中英

Proper way to add a lot of event listeners

I often add a bunch of event listeners to things in my sites — a header menu, a sidebar menu, some buttons, some toggles, etc. By the end of a project, there could be a whole bunch of event listeners operating on a page.

I always do this sort of thing:

// all of our menu items
var menuItems = document.querySelectorAll('.primary-nav a');

// loop over them
_.each (menuItems, function(item){
    // add event listener to each
    item.addEventListener('click', function(){
        console.log(item);
    });
});

So, on a given site, I might have 4-5 of those kinds of blocks. Is it better to have all these listeners out there, or is it better to listen on the document and employ some kind of class/attribute filtering?

Like so:

document.addEventListener('click', function(e){
    if ( e.target.closest('li').classList.contains('primary-nav') ) {
        // We have a primary nav item, do something with it
    }

    if ( e.target.closest('li').classList.contains('mobile-menu-toggle')) {
        // function for toggling open the mobile menu
    }
}); 

Advice very welcome!

It depends. Your first example is more performant and only does what you ask it to, in a very clean way. The second example (as others said, it's incomplete - there is no "closest" method) can be more effective if you expect the DOM's structure to change, but don't want to be re-adding event listeners.

If you expect to add a new primary-nav or mobile-menu-toggle , then having the one root listener will mean no listeners have to change even when adding/removing elements. Frameworks like JQuery allow for this sort of thing with syntax like this:

$('body').on('click', '.primary-nav', () => {
  ..
});

Similarly, the listener is added to body , but only responds to .primary-nav selector matchers. Keep in mind you should only use this when it makes sense based on the dynamic nature of a page; otherwise the "click" listener will get pretty complicated on a big page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM