Artículo original: Event Delegation in JavaScript –Explained with an Example
Delegación de eventos es un patrón basado en el concepto de Propagación de eventos (Event Bubbling). Es un patrón de manejo de eventos que permite gestionar eventos en un nivel superior del árbol del DOM, en lugar de hacerlo directamente en el nivel donde el evento fue inicialmente recibido.
Hay una versión en video de este tema si tú lo prefieres.
Una breve introducción a propagación de eventos.
Por defecto, los eventos desencadenados en un elemento se propagan hacia arriba en el árbol del DOM hasta el elemento padre, sus ancestros, y finalmente hasta el elemento raíz (html
).
Mira este ejemplo.
<div>
<span>
<button>Click Me!</button>
</span>
</div>
Aquí tenemos un, div
el cual es padre de un, span
quien a su vez es padre del elemento button
.
Debido a la propagación de eventos, cuando el botón recibe un evento, por ejemplo un clic, el evento se propaga hacia arriba en el árbol del DOM, por lo que el span
y el div
también recibirán el evento respectivamente.
Si quieres aprender acerca de propagación de eventos más a detalle, puedes leer un artículo sobre esto aquí .
¿Cómo funciona la delegación de eventos?
Con la delegación de eventos, en lugar de manejar el evento en el button
puedes manejarlo en el div
.
La idea es "delegar" el manejo de un evento a un elemento diferente (en este caso, el div, que es el elemento padre) en lugar del elemento actual (el botón) que recibió el evento.
Aquí tienes un ejemplo en código de lo que quiero decir:
const div = document.getElementsByTagName("div")[0]
div.addEventListener("click", (event) => {
if(event.target.tagName === 'BUTTON') {
console.log("button was clicked")
}
})
El objeto event
tiene una propiedad target
que contiene información sobre el elemento que realmente recibió el evento. Con target.element
obtenemos el nombre de la etiqueta del elemento y verificar si es BUTTON.
Con este código, cuando haces clic en el button
, el evento se propaga hacia arriba hasta el div
el cual maneja el evento.
Beneficios de la delegación de eventos.
La delegación de eventos es un patrón útil que te permite escribir código más limpio y reducir la cantidad de event listeners (escuchadores de eventos), especialmente cuando comparten una lógica similar.
¿A qué me refiero con esto? Mira este código:
<div>
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
</div>
Aquí tenemos 3 botones. Supongamos que queremos manejar un evento clic en cada botón, de manera que, al hacer clic, el texto del botón se registre en la consola. Podemos implementarlo de la siguiente manera:
const buttons = document.querySelectorAll('button')
buttons.forEach(button => {
button.addEventListener("click", (event) => {
console.log(event.target.innerText)
})
})
Usamos querySelectorAll
aquí porque devuelve un NodeList
, el cual permite usar el método forEach
. Por otro lado, getElementByTagName
devuelve una, HTMLCollection
el cual no tiene el método forEach
, por lo que no se podría iterar de la misma manera.
Cuando haces clic en el primer botón, se registra "Button 1" en la consola. Para el segundo botón, se registra "Button 2", y para el tercer botón, se registra "Button 3".
Aunque esto funciona como esperamos, hemos definido tres event listeners, uno para cada botón.
Dado que el evento clic en estos botones se propaga hacia arriba en el árbol del DOM, podemos usar un elemento padre ó ancestro común para manejar el evento. En este caso, delegamos la lógica a un elemento ancestro compartido, encargándose de gestionar el evento para todos los botones.
A continuación, te explicamos cómo:
const div = document.querySelector('div')
div.addEventListener("click", (event) => {
if(event.target.tagName === 'BUTTON') {
console.log(event.target.innerText)
}
})
Ahora, tenemos solo un event listener, pero la misma lógica: cuando haces clic en el primer botón, "Button 1" se registra en la consola, y lo mismo ocurre para los demás botones.
Incluso si agregamos un botón adicional como este:
<div>
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
<button>Button 4</button>
</div>
No tendremos que modificar el código JavaScript porque el nuevo botón también comparte el div
padre (el cual delegamos para manjera los eventos) con los otros botones.
Conclusión
Con la delegación de eventos, reduces la cantidad de event listeners y centralizas la lógica basada en eventos en solo lugar. Esto facilita agregar y remover elementos sin necesidad de agregar o remover manualmente event listeners existentes.
Delegación de eventos es posible, gracias la propagación de eventos en el DOM, donde el evento que recibe un elemento hijo también se transmite a su elemento, padre y ancestros. Nuevamente, puedes leer más acerca de propagación de evento aquí.
¡Gracias por leer, y happy coding!