Una aplicación de consola sigue un guion: pide un dato, espera, lo procesa. En el navegador el orden lo marca el usuario, que puede pulsar, escribir o hacer scroll en cualquier momento. JavaScript no se queda esperando: registra funciones que el navegador llamará cuando ocurra algo. Ese «algo» es un evento.
1 // Escuchar un evento
Para reaccionar a un evento necesitas tres cosas: el elemento, el tipo de evento y la función que se ejecutará. Se unen con addEventListener:
const boton = document.querySelector('#guardar');
function manejarClic() {
console.log('Has pulsado guardar');
}
boton.addEventListener('click', manejarClic);Aquí aparecen juntas dos ideas del módulo anterior. La función se pasa sin paréntesis, porque no quieres ejecutarla ahora sino entregarla. Y como es un callback, puede usar las variables del lugar donde se escribió gracias a los closures.
Un mismo elemento puede tener varios listeners para el mismo evento, y se ejecutarán en el orden en que se registraron.
Verás código antiguo con atributos en el HTML, como <button onclick="guardar()">, o con la propiedad boton.onclick = guardar. El atributo mezcla JavaScript con el marcado, y la propiedad sólo admite una función: asignar otra borra la anterior. Usa siempre addEventListener.
2 // El objeto evento
Cuando el navegador llama a tu función, le pasa como argumento un objeto evento con la información de lo que ha ocurrido. Por convención se llama e, ev o event:
boton.addEventListener('click', (e) => {
console.log(e.type); // 'click'
console.log(e.target); // el elemento sobre el que se hizo clic
});
document.addEventListener('keydown', (e) => {
console.log(e.key); // 'Enter', 'a', 'Escape'...
if (e.key === 'Escape') cerrarModal();
});
campo.addEventListener('input', (e) => {
console.log(e.target.value); // el texto actual del campo
});Además de las propiedades comunes, cada tipo de evento añade las suyas: los de ratón traen la posición (clientX, clientY), los de teclado la tecla (key) y los modificadores (ctrlKey, shiftKey).
3 // Los eventos que más vas a usar
| Evento | Cuándo se dispara | Uso típico |
|---|---|---|
click |
Al pulsar un elemento (también con teclado en botones) | Botones, enlaces, tarjetas |
input |
Cada vez que cambia el valor de un campo | Buscadores en vivo, contadores |
change |
Al confirmar un cambio (salir del campo, elegir opción) | select, casillas, ficheros |
submit |
Al enviar un formulario | Validar y enviar datos |
keydown |
Al pulsar una tecla | Atajos de teclado |
focus / blur |
Al entrar o salir de un campo | Mostrar ayudas o errores |
DOMContentLoaded |
Cuando el HTML está analizado | Arrancar la aplicación |
Para botones, usa click aunque pienses en teclado: el navegador lo dispara también al pulsar Enter o la barra espaciadora sobre un <button>. Si en su lugar pones un click sobre un <div>, la acción no será accesible desde el teclado.
4 // Comportamiento por defecto y limpieza
Muchos elementos ya hacen algo por sí mismos: un enlace navega, un formulario se envía y recarga la página, un clic derecho abre el menú contextual. El método preventDefault() cancela esa acción del navegador, pero no detiene tu código:
formulario.addEventListener('submit', (e) => {
e.preventDefault(); // el formulario no recarga la página
// aquí validas y envías los datos con JavaScript
});Para dejar de escuchar un evento se usa removeEventListener con exactamente la misma función que se registró. Por eso, si piensas quitar un listener, no puedes usar una flecha anónima al registrarlo. Si sólo necesitas que se ejecute una vez, hay una opción más cómoda:
boton.addEventListener('click', mostrarBienvenida, { once: true });Un campo de búsqueda debe mostrar debajo cuántos caracteres llevas escritos y avisar en rojo si pasas de 30.
<input id="buscar" type="search">
<p id="contador">0 / 30</p>- Elegir el evento:
changesólo se dispara al salir del campo; para reaccionar en cada pulsación se necesitainput. - Leer el valor desde el evento:
e.target.value.lengthda la longitud actual, sin tener que volver a seleccionar el campo. - Actualizar el texto:
contador.textContent = `${longitud} / 30`;. - Reflejar el estado con una clase:
contador.classList.toggle('excedido', longitud > 30);y el CSS pinta.excedidoen rojo.
const buscar = document.querySelector('#buscar');
const contador = document.querySelector('#contador');
buscar.addEventListener('input', (e) => {
const longitud = e.target.value.length;
contador.textContent = `${longitud} / 30`;
contador.classList.toggle('excedido', longitud > 30);
});5 // Para practicar
Botones que muestran y ocultan contenido, un contador en vivo y un atajo de teclado. Cada ejercicio trae el enunciado en los comentarios del código.
Ocultar contenidos y contar caracterestraining-daw-sv/modulo-01/03-eventos/01_hide_contentsAutoevaluación
Tu programa Java de consola lee una opción con Scanner y se queda esperando. En el navegador no escribes nada parecido para esperar un clic. ¿Cómo se consigue reaccionar a él?
Un removeEventListener('click', () => guardar()) no elimina el listener que se añadió con la misma línea. ¿Por qué?
removeEventListener busca exactamente la misma referencia que se registró. Para poder quitarlo hay que guardar la función en una constante y usar esa constante en las dos llamadas.Un formulario recarga la página al pulsar «Enviar» y el mensaje de confirmación que pintas desaparece al instante. ¿Qué falta?
event.preventDefault() en el listener de submit. Enviar un formulario es un comportamiento por defecto del navegador: navega a la URL del atributo action, o recarga la misma página. Tu código se ejecuta, pero la navegación posterior borra el resultado.