En capítulos anteriores hemos estado viendo conceptos importantes como son la declaración de los eventos, como remover, como pasar parámetros cuando lo necesitemos, como detener el flujo de la propagación dependiendo si tenemos la fase de burbuja o captura.
A día de hoy vamos a ver un concepto muy importante, utilizado por librerías como React, Vue, Angular.. que es como manejan el esquema de los eventos, y esto optimiza mucho a nivel de recursos y de memoria nuestras aplicaciones, y se trata de la delegación de los eventos.
Que es la delegación de eventos
En vez de asignar listeners a todos los elementos, podemos tener el listener asignado a un elemento padre superior, y a partir de ahí, simplemente, buscando el selector que coincida para ver quien originó el evento, desencadenar la programación que necesitemos al momento del evento. Por ejm, en un formulario complejo, con muchos inputs, en lugar de asignar el evento a cada input, asignárselo al formulario como tal, e incluso ir un paso más, y se podría asignar el evento al nodo raíz, que en este caso es el document, que es lo que en muchos casos se está haciendo en la actualidad. Se genera un listener global para el document, todos los eventos los pegamos al document, y a partir de ahí detectamos cual es el nodo que nos interesa que active el evento, y desencadenamos la programación, de tal manera que en lugar de tener muchos listeners generados al evento click, tenemos un sólo listener generado al document, y simplemente detectamos cual es el elemento que va a desencadenar el evento.
La delegación de eventos, por otro lado evita la propagación, ya no tenemos que estar deteniendo la propagación, porque ya el evento está asignado al nodo superior que es el document.
Lo vamos a ver con un ejm.
Ejm
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Flujo de eventos</title> <style> .eventos-flujo div { padding: 4rem; font-size: 2rem; text-align: center; } .uno { background-color: yellow; } .dos { background-color: gold; } .tres { background-color: lightyellow; } </style> </head> <body> <h1>Flujo de eventos</h1> <section class="eventos-flujo"> <div class="uno"> 1 <div class="dos"> 2 <div class="tres"> 3 <a href="https://sutilweb.eu" target="_blank" rel="noopener">Sutil Web</a> </div> </div> </div> </section> <script> // Vamos a crear previamente la función flujoEventos // de donde va a tirar nuestro bucle forEach function flujoEventos(e) { console.log(`Hola, te saluda ${this}, el clic lo originó ${e.target.className}`); } document.addEventListener("click", (e) => { console.log("Click en", e.target); if(e.target.matches(".eventos-flujo div")) { flujoEventos(e); } /* Buscar la coincidencia en un condicional y dentro del condicional ejecutar la programación que necesitemos para cada elemento del DOM al que tengamos que asignar el evento click */ if(e.target.matches(".eventos-flujo a")) { alert(`Hola, soy Francisco Paredes`); e.preventDefault(); } }) </script> </body> </html
Como podemos ver, el código se vuelve más sencillo. Con esta técnica, a parte de mejorar el rendimiento a nivel de memoria y de recursos, de nuestras aplicaciones, solamente estamos teniendo una sola asignación al evento click, y la programación que necesitemos ejecutar en cada uno de los elementos del DOM que haya que programar, lo hacemos con un condicional el cual va evaluando que coincida el selector con el que queremos que ese elemento aplique la programación.
Esta técnica es muy importante en peticiones asíncronas, es decir, cuando utilizamos Ajax o Fetch y generamos elementos dinámicos.
Nota: esta es la manera más óptima de trabajar con los eventos en Javascript.