CodeForge

JavaScript de Cero a Experto / Eventos y listeners

Burbujeo y captura: los eventos viajan

Teoría20 min20 XP

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

frenar.js
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.