Hoy · Hoja de ruta
- 1. Aprende: Qué información trae el evento, cómo se propaga y qué es delegar.
- 2. Haz: Un solo manejador que atienda a todas las tarjetas del catálogo.
- 3. Comprueba: Funciona también con las tarjetas que aún no existen.
Antes de empezar · 5 minutos, sin apuntes
- Si tienes cincuenta botones iguales, ¿registrarías cincuenta escuchas?
- ¿Cómo sabrías cuál de ellos se ha pulsado?
- ¿Qué pasa con los botones que se crean después?
El objeto que recibe el manejador
catalogo.addEventListener("click", (evento) => {
evento.target; // el elemento exacto donde se pulsó
evento.currentTarget; // el elemento que escucha
evento.type; // "click"
evento.key; // en eventos de teclado
evento.preventDefault();
evento.stopPropagation();
});
La pareja target / currentTarget es la clave de esta sesión: puedes escuchar en el contenedor y averiguar dentro cuál de sus hijos recibió la acción.
La propagación
Un clic no ocurre solo en un elemento: recorre el árbol.
- Captura · del documento hacia abajo
- Objetivo · el elemento pulsado
- Burbujeo · hacia arriba, hasta el documento
El burbujeo es lo que hace posible la delegación y explica además un fallo característico: pulsar en un botón dentro de una tarjeta que también escucha el clic dispara los dos manejadores.
stopPropagation es el último recurso
Detener la propagación arregla el síntoma y deja una trampa: cualquier manejador que alguien registre más arriba —cerrar un menú, un contador de uso— dejará de enterarse, y quien lo escriba no entenderá por qué.
Antes de detenerla, comprueba si el manejador de arriba puede filtrar por target. Casi siempre puede.
Delegar
catalogo.addEventListener("click", (evento) => {
const boton = evento.target.closest("[data-accion='añadir']");
if (!boton) return; // el clic no era en un botón nuestro
const id = Number(boton.dataset.id);
añadirAlCarrito(id);
});
Tres ventajas, y son grandes: una sola escucha en lugar de cincuenta; funciona con las tarjetas que tu código creará después; y no hay que registrar nada de nuevo tras volver a pintar.
closest
Sube por los antepasados desde el elemento pulsado hasta encontrar uno que case con el selector. Resuelve el problema de que el clic caiga en un icono o en el texto de dentro del botón, y no en el botón mismo.
Teclado, siempre
buscador.addEventListener("keydown", (evento) => {
if (evento.key === "Escape") limpiarBusqueda();
});
Si delegas clics en elementos que son botones de verdad, el teclado ya funciona: pulsar Intro sobre un botón genera un click. Es otra razón para usar el elemento correcto en lugar de un div decorado.
Tarea 5 · Un manejador para todos
- Añade a cada tarjeta de tu catálogo un botón con
data-accionydata-id. - Registra una sola escucha en el contenedor.
- Usa
closestpara localizar el botón ydatasetpara el identificador. - Añade una segunda acción y distíngula por su
data-accion. - Comprueba con el teclado que ambas funcionan.
- Registra una escucha en el contenedor y otra en la tarjeta, y observa el orden.
stopPropagation rompería otra funcionalidad.Checkpoint · fin de la sesión 5
- Distingues
targetdecurrentTarget. - Explicas el burbujeo con un ejemplo de tu página.
- Delegas con
closesty sales pronto si no procede. - Todo lo que funciona con ratón funciona con teclado.
Antes de cerrar · 2 minutos, sin mirar
- ¿Qué ventaja tiene delegar?
- ¿Para qué sirve
closest? - ¿Por qué evitamos
stopPropagation?
Ver respuestas
1 · Una sola escucha, y funciona con los elementos creados después.
2 · Para subir desde el elemento pulsado hasta el contenedor que te interesa, aunque el clic cayera en un icono interior.
3 · Porque impide que otros manejadores más arriba se enteren del evento, y eso rompe cosas a distancia.