Delegation Pattern en JavaScript: Mejora de Eventos Click en Listas

Clase 19 de 27Curso de JavaScript: Manipulación del DOM

Contenido del curso

Manipulando Elementos del DOM

Creando un Administrador de Tareas

Resumen

Agregar un event listener a cada elemento del DOM puede parecer la solución más directa, pero cuando la lista crece, el rendimiento se resiente. Existe una técnica mucho más eficiente que aprovecha cómo los eventos se propagan en el árbol del DOM: el Delegation Pattern. Este patrón permite registrar un único evento en el elemento padre y dejar que él decida qué hacer según el hijo que recibió la interacción.

¿Qué es el bubbling y por qué importa en el manejo de eventos?

Cuando haces clic en cualquier elemento HTML, ese evento no se queda ahí. El evento sube por el árbol del DOM, pasando por cada elemento padre hasta llegar al documento raíz. Este comportamiento se conoce como bubbling [0:10]. Si alguno de esos elementos padre tiene un event listener registrado para ese tipo de evento, lo detectará y podrá ejecutar una acción.

Esta característica del DOM es precisamente lo que hace posible el Delegation Pattern: en lugar de escuchar en cada hijo, escuchas en el padre y dejas que el bubbling haga el trabajo.

¿Cómo funciona agregar eventos de forma individual a cada elemento?

La primera aproximación consiste en seleccionar todos los elementos <li> del HTML y recorrerlos para asignarles un evento a cada uno [1:42].

javascript const listItems = document.querySelectorAll('li');

listItems.forEach((item) => { item.addEventListener('click', (event) => { event.target.classList.toggle('highlights'); }); });

  • Se usa querySelectorAll('li') para obtener una lista de nodos con todas las etiquetas <li> del documento [2:00].
  • Con forEach se itera sobre cada nodo y se le agrega un event listener de tipo click [2:20].
  • Dentro del callback, el objeto event.target representa el elemento exacto que recibió el clic.
  • El método classList.toggle('highlights') agrega la clase CSS si no existe, o la quita si ya está presente [2:55].

Este enfoque funciona, pero no es la mejor práctica. Si tienes 100 elementos, estás registrando 100 listeners independientes, lo que impacta directamente el performance de la aplicación [3:35].

¿Qué hace classList.toggle exactamente?

El método toggle en la propiedad classList es un atajo muy útil: verifica si la clase existe en el elemento y, de ser así, la elimina. Si no existe, la agrega [3:10]. Esto evita tener que escribir lógica condicional para añadir o remover clases manualmente.

¿Cómo aplicar el Delegation Pattern para mejorar el rendimiento?

En lugar de registrar múltiples eventos, el Delegation Pattern propone agregar un solo evento al elemento padre y delegar la responsabilidad de identificar cuál hijo fue clickeado [3:50].

javascript const list = document.querySelector('ul');

list.addEventListener('click', (event) => { const li = event.target.closest('li'); if (li) { li.classList.toggle('highlights'); } });

  • Se selecciona el elemento <ul> como contenedor padre con querySelector('ul') [4:05].
  • Se registra un único event listener de tipo click sobre ese padre.
  • Se utiliza el método closest('li') sobre el event.target para encontrar el elemento <li> más cercano al punto donde ocurrió el clic [4:40].

¿Por qué se necesita el método closest?

Aquí está el detalle clave. Si un <li> contiene internamente otras etiquetas como un <p> o un <span>, al hacer clic sobre ese texto el event.target sería el párrafo, no el <li> [5:30]. Sin closest, solo cambiaría el background del párrafo interno, no el del <li> completo.

El método closest recorre el DOM hacia arriba desde el elemento que recibió el clic y devuelve el primer ancestro que coincida con el selector indicado [5:10]. Esto garantiza que siempre se aplique el toggle sobre la etiqueta <li>, sin importar qué estructura interna tenga.

Con un solo listener en el padre, reduces la carga de memoria y mantienes el código limpio y escalable. Si mañana agregas más elementos <li> dinámicamente, el evento seguirá funcionando sin necesidad de registrar nuevos listeners.

¿Ya usas el Delegation Pattern en tus proyectos o sigues registrando eventos individuales? Comparte tu experiencia y cómo este cambio ha impactado tu código.