Event delegation Show archive.org snapshot is a pattern where a container element has a single event listener that handles events for all descendants that match a CSS selector.
This pattern was popularized by jQuery that lets you do this:
$('.container').on('click', '.message', function(event) {
console.log("A message element was clicked!")
})
This technique has some advantages:
This technique has some disadvantages:
.message
element was hit. This can degrade performance when you deal with fast-firing events like scroll
or mousemove
. Performance will be fine with events that fire less frequently, like click
, keydown
or submit
.Event#stopPropagation()
Show archive.org snapshot
to control the
event's bubbling
Show archive.org snapshot
within its descendants. The event has already bubbled up to the container and stopPropagation()
will only prevent it from bubbling up to the container's own ancestors.Info
jQuery has some complicated code in place to mitigate (2) and (3) for events listeners registered through
jQuery#on()
Show archive.org snapshot .
There is no built-in browser API to do event delegation in the style of
jQuery#on()
Show archive.org snapshot
. However, it is not hard to build this on your own, or use one of many libraries that do it for you.
Register a standard event listener to your target. Before you run your callback, check that the actual element (event.target
) matches the desired selector, or has the desired selector in its ancestors:
let container = document.querySelector('.container')
container.addEventListener('click', function(event) {
if (event.target.closest('.message')) {
console.log('A message was clicked!')
}
})
If you do this a lot, you may want to define a function to do it for you:
function addMatchingEventListener(element, eventType, selector, listener, ...optionsArgs) {
element.addEventListener(eventType, ...optionsArgs, (event) => {
let target = event.target
if (target && target.closest(selector)) {
listener.call(this, event)
}
})
}
Use it like this:
addMatchingEventListener(container, 'click', '.message', function(event) {
console.log("A message was clicked!")
}
If you're using
Unpoly
Show archive.org snapshot
you can use
up.on()
Show archive.org snapshot
to register a delegating event listener:
up.on(container, 'click', '.message', function(event) {
console.log("A message was clicked!")
}
Also see