Reader feedback on event bubbling with lots of items
Yesterday, I looked briefly as how to handle event bubbling with lots of items.
The article was kind of a shoulder shrug, but I got some great responses back from readers (shared with permission).
Dillon Headley wrote:
The key here is probably making named functions that can be called and not just have all your event handler code within there I would think…
What he means is something like this.
// Instead of this...
document.addEventListener('click', function (event) {
if (event.target.closest('.scroll')) {
// Do something...
}
if (event.target.matches('[data-some-attribute]')) {
// Do something else...
}
if (event.target.matches('#my-form')) {
// Do another thing...
}
}, false);
// Do this...
document.addEventListener('click', function (event) {
animate(event);
sayHi(event);
submitForm(event);
}, false);
Your listener contains nothing but functions, and you move the logic and if
checks out to them instead. This is solid functional programming.
Longtime reader Judd Franklin had a really interesting solution that builds on what Dillon suggested: using data attributes in the markup as event hooks. This is common in things like React and Vue.
How that might work
First, let’s setup a function called jetpack()
.
var jetpack = function () {
'use strict';
};
// Run jetpack()
jetpack();
Inside our function, we’ll create an object to hold all of our methods, and then add our methods to it. For this example, I’ll create a method to open an alert window, and another to log to the console.
var jetpack = function () {
'use strict';
// Setup methods object
var methods = {};
methods.alert = function (event) {
alert(event.target.textContent);
};
methods.log = function (event) {
console.log(event.target.textContent);
};
};
// Run jetpack()
jetpack();
Finally, we’ll setup an event listener.
Inside it, we’ll check to see if the clicked element has some data attribute—let’s use data-jetpack
for this example. If it does, we’ll get the value and use it as a key to check for a matching function in the methods
object.
If one exists, we’ll run it.
var jetpack = function () {
'use strict';
// Setup methods object
var methods = {};
methods.alert = function (event) {
alert(event.target.textContent);
};
methods.log = function (event) {
console.log(event.target.textContent);
};
document.addEventListener('click', function (event) {
var method = event.target.getAttribute('data-jetpack');
if (!method || !methods[method]) return;
methods[method](event);
}, false);
};
// Run jetpack()
jetpack();
In our markup, we can add a [data-jetpack]
attribute to any item you want to run, and use the function you want as the attribute value.
<button data-jetpack="alert">Click Me!</button>
<button data-jetpack="log">Click Me, Too!</button>
<button>I do nothing =(</button>