JavaScript de Cero a Experto / Eventos y listeners
Burbujeo y captura: los eventos viajan
Haces clic en un botón… y el evento no se queda en el botón: sube por sus
ancestros — el div que lo contiene, la sección, el body, el documento —
avisándole a cada uno. Ese viaje se llama burbujeo, confunde a medio mundo
la primera vez, y es justamente lo que hace posible el patrón estrella de
la próxima lección.
La queja que sube de piso en piso
Haz clic en el botón y mira la consola: TRES reportes de un solo clic, en
orden de subida — botón, torre, conjunto. En los tres, target es
boton (donde nació, nunca cambia), mientras currentTarget va cambiando
según quién lo escucha. Ahora haz clic en la zona de la torre sin tocar el
botón: dos reportes, y el target ya no es el botón. El acta siempre dice
la verdad sobre el origen.
target vs currentTarget: tatuaje mental
event.target→ el elemento donde el evento NACIÓ (el más profundo bajo el clic). No cambia durante el viaje.event.currentTarget→ el elemento dueño del LISTENER que se está ejecutando. En cada nivel del viaje, es ese nivel.
Cuando el listener está en el mismo elemento clicado, ambos coinciden y ni notas la diferencia. La diferencia explota — y esta distinción se vuelve oro — cuando escuchas en un ancestro… que es exactamente el plan de la próxima lección.
Frenar el viaje: stopPropagation
boton.addEventListener("click", (event) => {
// el evento muere aquí: los ancestros no se enteran
event.stopPropagation();
});Existe, y a veces se necesita — el caso clásico: un clic dentro de un modal
no debe llegar al fondo oscurecido que lo cierra. Pero úsalo como último
recurso, con una nota honesta de por medio: un evento frenado no les llega
a ancestros que quizá lo necesitaban (analíticas, menús que se cierran, la
delegación que viene). Si tu primera solución a todo es frenar el burbujeo,
casi siempre hay un diseño mejor. Y no lo confundas con su vecino:
preventDefault frena la ACCIÓN por defecto (recargar, navegar);
stopPropagation frena el VIAJE del evento. Independientes por completo.
Última pieza del mapa, por honestidad técnica: antes de subir, el evento
BAJA — una fase llamada captura, de documento a botón, en la que casi
nadie escucha (requiere { capture: true } explícito). El 99% del código
real vive en el burbujeo; te la presento para que el término no te asuste
en una entrevista.
Tienes un listener de click en un div contenedor. El usuario hace clic en un botón que está adentro del div. Dentro del listener, ¿qué valen event.target y event.currentTarget?
Mini-reto
En el playground del edificio: 1) agrega un stopPropagation() en el
listener del botón y comprueba que torre y conjunto dejan de reportar; 2)
quítalo y ahora escucha también en document (cuarto nivel) — ¿cuántos
reportes ves por clic?; 3) predice ANTES de hacer clic en cada zona qué
dirá cada reporte (escuchado en / nació en), y verifica. Si aciertas
las tres, el burbujeo ya es tuyo.
Qué sigue
Ya sabes que el clic de CUALQUIER hijo llega al padre, y que target
delata cuál fue. Junta las piezas: ¿para qué ponerle listener a cada botón
de una lista de 100 gastos… si UN listener en la lista los escucha a
todos — incluidos los que aún no existen? Eso es delegación de eventos, la
próxima lección y el patrón favorito de las entrevistas.