Eventos en JavaScript
En esta lección
- addEventListener
- Eventos más usados
- El objeto event
- Varios manejadores y quitar manejadores
- Eventos de ratón
- La propagación de eventos
- Delegación de eventos
- Un mismo manejador para muchos elementos
- Manejadores en el HTML: evítalos
- Formularios y preventDefault
- Leer lo que escribe el usuario en tiempo real
- Junta todo
Un evento es algo que pasa en la página: un clic, una tecla, el envío de un formulario, el scroll… Con JavaScript puedes escuchar esos eventos y ejecutar código cuando ocurren. Es lo que hace que una web sea interactiva.
addEventListener
const boton = document.querySelector("#saludar");
boton.addEventListener("click", () => {
alert("¡Hola!");
});
Se lee así: “cuando alguien haga click en el botón, ejecuta esta función”. Tiene dos partes:
- El tipo de evento, como texto:
"click". - La función que se ejecuta cuando ocurre.
También puedes pasar una función con nombre (sin paréntesis, porque no la estás llamando todavía):
function saludar() {
alert("¡Hola!");
}
boton.addEventListener("click", saludar);
Eventos más usados
| Evento | Cuándo ocurre |
|---|---|
click | Al pulsar un elemento |
input | Cada vez que cambia el texto de un campo |
change | Al cambiar un select, checkbox o al salir de un campo |
submit | Al enviar un formulario |
keydown | Al pulsar una tecla |
mouseenter / mouseleave | Al entrar o salir el ratón de un elemento |
DOMContentLoaded | Cuando el HTML ha terminado de cargar |
El objeto event
La función recibe un objeto con información sobre lo que ha pasado:
document.addEventListener("keydown", (evento) => {
console.log("Has pulsado", evento.key);
});
boton.addEventListener("click", (evento) => {
console.log(evento.target); // el elemento en el que se hizo clic
});
Varios manejadores y quitar manejadores
Un mismo evento puede tener varios manejadores: basta con llamar varias veces a addEventListener. Se ejecutan en el orden en que se registraron.
Para quitar un manejador, usa removeEventListener con la misma función (por eso necesita tener nombre):
boton.removeEventListener("click", saludar);
Si solo quieres que un manejador se ejecute una vez: boton.addEventListener("click", saludar, { once: true });.
Eventos de ratón
| Evento | Cuándo |
|---|---|
click / dblclick | Clic / doble clic |
mouseenter / mouseleave | El ratón entra / sale del elemento |
mouseover / mouseout | El ratón entra / sale del elemento o de cualquiera de sus hijos |
mousemove | El ratón se mueve encima |
mousedown / mouseup | Se pulsa / se suelta el botón |
La diferencia entre mouseleave y mouseout confunde mucho: si un <div> tiene un párrafo dentro, al pasar el ratón del div al párrafo, mouseout se dispara (has “salido” del div hacia su hijo) y mouseleave no (sigues dentro del div). Normalmente quieres mouseenter y mouseleave.
Hoy la mayoría de dispositivos son táctiles, así que no hagas que nada importante dependa de pasar el ratón por encima: en un móvil no existe. Para interfaces que deben funcionar con ratón, dedo y lápiz a la vez, existen los eventos pointerdown, pointermove y pointerup.
La propagación de eventos
Cuando haces clic en un elemento, el evento no se queda ahí: sube por todos sus antepasados. Si haces clic en una imagen que está dentro de un botón, que está dentro de una tarjeta, que está dentro de un <div>, el clic llega a la imagen, al botón, a la tarjeta y al div. A esto se le llama burbujeo (bubbling).
En cualquiera de ellos puedes saber dónde empezó el evento:
evento.target: el elemento donde se hizo clic realmente (la imagen).evento.currentTarget: el elemento que tiene el manejador que se está ejecutando.
Si en algún caso necesitas que el evento no siga subiendo, usa evento.stopPropagation(). Úsalo poco: rompe comportamientos que otros manejadores esperan.
Delegación de eventos
Imagina una lista de 100 tareas, cada una con su botón de borrar. Podrías poner 100 manejadores, uno por botón. Pero gracias a la propagación, basta con uno en el contenedor:
const lista = document.querySelector("#tareas");
lista.addEventListener("click", (evento) => {
const boton = evento.target.closest(".borrar");
if (!boton) return; // el clic no fue en un botón de borrar
boton.closest("li").remove(); // borra la tarea de ese botón
});
Ventajas:
- Un solo manejador en lugar de cientos.
- Funciona también con los elementos que añadas después, sin tener que registrarles nada. Es perfecto para contenido creado dinámicamente.
closest(selector) busca, desde el elemento hacia arriba, el primero que cumple el selector. Es imprescindible aquí, porque evento.target puede ser el icono que hay dentro del botón y no el botón mismo.
Un mismo manejador para muchos elementos
Otra técnica útil: un solo manejador que sabe qué elemento recibió el evento gracias a su id o a sus atributos data-*:
function mostrarFoto(evento) {
const id = evento.currentTarget.dataset.foto;
visor.src = `img/${id}.jpg`;
}
for (const miniatura of document.querySelectorAll(".miniatura")) {
miniatura.addEventListener("click", mostrarFoto);
}
Manejadores en el HTML: evítalos
En código antiguo verás cosas como estas:
<button onclick="saludar()">Hola</button>
<body onload="iniciar()">
boton.onclick = saludar;
Funcionan, pero mezclan HTML y JavaScript, solo permiten un manejador por evento y dan problemas de seguridad. Usa siempre addEventListener.
Formularios y preventDefault
Al enviar un formulario, el navegador recarga la página. Si quieres gestionarlo con JavaScript, tienes que impedirlo:
formulario.addEventListener("submit", (evento) => {
evento.preventDefault();
const email = document.querySelector("#email").value;
console.log("Email:", email);
});
Escucha el submit del formulario, no el click del botón: así también funciona cuando alguien pulsa Enter.
Leer lo que escribe el usuario en tiempo real
const buscador = document.querySelector("#buscar");
buscador.addEventListener("input", () => {
console.log("Buscando:", buscador.value);
});
.value siempre es un texto. Si esperas un número, conviértelo con Number().
Junta todo
El ejemplo de abajo combina lo que has aprendido: un formulario, el DOM, eventos y funciones. Es una lista de tareas completa en menos de 30 líneas. Modifícala: añade un botón para borrar todas o muestra la fecha de cada tarea.
Pruébalo tú
Cambia el código y pulsa Ejecutar (o Ctrl + Enter).
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.