Introducción a los eventos del navegador en JavaScript
Aprende cómo funcionan los eventos del navegador en JavaScript: tres formas de agregar manejadores, addEventListener vs onclick, el objeto evento y más.
Dominando los eventos del navegador en JavaScript
Un evento del navegador es una señal de que algo ha ocurrido en la página: el usuario hizo clic en un botón, se presionó una tecla, una imagen terminó de cargar, la ventana se redimensionó. Reaccionar a estas señales es lo que convierte un documento estático en una aplicación interactiva.
Esta guía explica qué son los eventos, las tres formas de escucharlos (y cuál es la preferida), qué información ofrece el objeto evento, cómo dejar de escuchar, y recorre seis ejemplos prácticos y ejecutables. Si eres nuevo en el lenguaje, comienza primero con la introducción a JavaScript.
Entendiendo los eventos del navegador
Un evento es una acción u ocurrencia que el navegador detecta y permite que tu código responda. Los eventos se dividen en dos grandes grupos:
- Eventos iniciados por el usuario — hacer clic con el ratón, escribir, mover el puntero, enviar un formulario.
- Eventos iniciados por el sistema — la página termina de cargar, una imagen no se carga, una animación CSS finaliza, la ventana se redimensiona.
Tipos de eventos
Estos son algunos de los eventos más comunes, agrupados por categoría:
| Categoría | Eventos |
|---|---|
| Ratón | click, dblclick, mouseover, mouseout, mousedown, mouseup |
| Teclado | keydown, keyup (keypress está obsoleto) |
| Formulario | submit, change, input, focus, blur |
| Documento / ventana | DOMContentLoaded, load, resize, scroll, beforeunload |
Cada categoría tiene su propio capítulo dedicado: consulta eventos de ratón, eventos de teclado, eventos de envío de formularios y eventos de carga de recursos.
Tres formas de agregar manejadores de eventos
Hay tres formas de reaccionar a un evento, ordenadas de menor a mayor flexibilidad.
1. Atributo HTML (onclick="...") — rápido, pero mezcla JavaScript en el marcado y solo permite un manejador. Evítalo en proyectos reales.
<button onclick="alert('Button clicked!')">Click Me!</button>2. Propiedad del DOM (element.onclick) — mantiene el código en JavaScript, pero asignar un nuevo manejador sobreescribe el anterior, por lo que sigue habiendo solo un manejador por evento.
<button id="myButton">Click Me!</button>document.getElementById('myButton').onclick = function () {
alert('Button clicked!');
};3. addEventListener (recomendado) — el enfoque estándar. Puedes adjuntar múltiples manejadores para el mismo evento, controlar la fase de captura/burbuja y eliminar el manejador más adelante.
<button id="myButton">Click Me!</button>document.getElementById('myButton').addEventListener('click', function () {
alert('Button clicked!');
});addEventListener es preferido porque permite registrar múltiples listeners para el mismo evento y ofrece un control más preciso del manejo de eventos — por ejemplo, llamar a event.stopPropagation() o event.preventDefault(). También acepta un object de opciones: { once: true } ejecuta el manejador una sola vez, y { capture: true } escucha durante la fase de captura (consulta bubbling y captura).
Eliminar un listener de eventos
Un listener permanece adjunto hasta que lo eliminas (o el elemento es eliminado por el recolector de basura). Para eliminarlo debes pasar la misma referencia de función que agregaste — una función anónima en línea no puede eliminarse porque no existe referencia a ella.
function handleClick() {
console.log('clicked');
}
const btn = document.getElementById('myButton');
btn.addEventListener('click', handleClick);
// later — stops the handler from firing again
btn.removeEventListener('click', handleClick);El objeto evento
Cuando se dispara un evento, el navegador crea un objeto evento que describe lo ocurrido y lo pasa como primer argumento al manejador. Las propiedades más útiles son:
event.type— el nombre del evento, p. ej."click".event.target— el elemento que activó realmente el evento.event.currentTarget— el elemento al que está adjunto el listener (equivale athisen un manejador con función regular).event.preventDefault()— cancela la acción predeterminada del navegador (p. ej. seguir un enlace).event.stopPropagation()— detiene la propagación del evento hacia los elementos ancestros.
<button id="myButton">Click Me!</button>
<div style="margin-top:10px;" id="eventInfo"></div>
<script>
document.getElementById('myButton').addEventListener('click', function(event) {
var eventInfo = 'Event Type: ' + event.type + '<br />Clicked Element: ' + event.target.tagName;
document.getElementById('eventInfo').innerHTML = eventInfo;
});
</script>Ejemplos prácticos de manejo de eventos del navegador
Veamos algunos ejemplos prácticos que muestran cómo manejar eventos del navegador en situaciones reales.
Ejemplo 1: Evento de envío de formulario
Manejar el envío de un formulario para validar la entrada antes de enviar datos al servidor:
<form id="loginForm">
Username: <input type="text" name="username" required />
Password: <input type="password" name="password" required />
<button type="submit">Login</button>
</form>
<script>
document.getElementById('loginForm').addEventListener('submit', function(event) {
event.preventDefault(); // Prevent the form from submitting normally
if (this.username.value.length < 4 || this.password.value.length < 4) {
alert('Username and password must be at least 4 characters long.');
} else {
this.submit(); // Submit the form manually if validation passes
alert('successfully submitted');
}
});
</script>(Nota: Aquí se usa una función regular en lugar de una función flecha para preservar el contexto de this, lo que permite que this.username y this.password hagan referencia correctamente a los elementos del formulario.)
Ejemplo 2: Manejo de eventos mouseover y mouseout
Cambiar el estilo de un botón cuando el ratón pasa por encima y restaurarlo cuando sale:
<button id="hoverButton">Hover Over Me!</button>
<script>
const button = document.getElementById('hoverButton');
button.addEventListener('mouseover', function() {
this.style.backgroundColor = 'green';
});
button.addEventListener('mouseleave', function() {
this.style.backgroundColor = '';
});
</script>Ejemplo 3: Eventos de teclado
Ejecutar una función cuando se presiona la tecla Enter:
<input type="text" id="inputField" placeholder="Type something and press Enter" />
<script>
document.getElementById('inputField').addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
alert('You pressed Enter!');
}
});
</script>Ejemplo 4: Funcionalidad de arrastrar y soltar
Implementar arrastrar y soltar para una transferencia sencilla de imágenes dentro de una página web:
<span>Drop image below</span>
<div id="dragArea" style="width: 300px; height: 300px; border: 2px dashed #ccc;">
</div>
<img id="draggableImage" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Crect width='150' height='150' fill='%234f46e5'/%3E%3Ctext x='75' y='80' fill='white' font-size='18' text-anchor='middle'%3EDrag me%3C/text%3E%3C/svg%3E" draggable="true" style="width: 150px; height: 150px;">
<script>
const dragArea = document.getElementById('dragArea');
const draggableImage = document.getElementById('draggableImage');
// Event listener for the drag start
draggableImage.addEventListener('dragstart', function(event) {
event.dataTransfer.setData("text/plain", event.target.id);
});
// Event listener for dragging over the drag area
dragArea.addEventListener('dragover', function(event) {
event.preventDefault(); // Necessary to allow the drop
});
// Event listener for drop
dragArea.addEventListener('drop', function(event) {
event.preventDefault(); // Prevent default behavior (like opening as link for some elements)
const data = event.dataTransfer.getData("text/plain");
const image = document.getElementById(data);
dragArea.appendChild(image);
});
</script>Explicación:
- Inicio del arrastre: Al comenzar a arrastrar la imagen, el ID de la imagen se guarda en los datos de arrastre.
- Arrastre sobre el área: Prevenir la acción predeterminada es necesario para permitir soltar el elemento.
- Soltar: Al soltar, la imagen se mueve al área de destino.
Ejemplo 5: Eventos de inicio y fin de animación
Usar animaciones CSS y manejar su inicio y fin con JavaScript:
<div id="animateBox" style="width: 100px; height: 100px; background: red; position: relative; animation: moveBox 5s 2;"></div>
<div id="animationStatus"></div>
<style>
@keyframes moveBox {
0% { left: 0; }
50% { left: 200px; }
100% { left: 0; }
}
</style>
<script>
const box = document.getElementById('animateBox');
const statusDisplay = document.getElementById('animationStatus');
box.addEventListener('animationstart', function() {
statusDisplay.innerHTML = 'Animation started';
});
box.addEventListener('animationend', function() {
statusDisplay.innerHTML = 'Animation ended';
});
box.addEventListener('animationiteration', function() {
statusDisplay.innerHTML = 'Animation iteration';
});
</script>(Nota: animationstart y los eventos relacionados son estándar en los navegadores modernos. Las versiones antiguas de Safari pueden requerir prefijos de proveedor como -webkit-animationstart, pero se recomiendan los nombres estándar para el desarrollo actual.)
Explicación:
animationstartse dispara una vez cuando comienza la animación.animationiterationse dispara al inicio de cada repetición — útil cuando una animación está configurada para ejecutarse varias veces.animationendse dispara una vez cuando la animación termina. Eldiv#animationStatusse actualiza en cada evento para dar retroalimentación en tiempo real en la página.
Ejemplo 6: Eventos personalizados
Crear y despachar eventos personalizados para manejar escenarios específicos de la aplicación:
<button id="customEventButton">Trigger Custom Event</button>
<script>
// Creating a custom event
const myEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Custom event triggered' }
});
// Event listener for custom event
document.addEventListener('myCustomEvent', function(event) {
alert('Event Message: ' + event.detail.message);
});
// Dispatch the custom event when button is clicked
document.getElementById('customEventButton').addEventListener('click', function() {
document.dispatchEvent(myEvent);
});
</script>Explicación:
- Creación del evento personalizado: Define un evento personalizado con datos adicionales (
detailque contiene un mensaje). - Manejo del evento: Configura un listener para el evento personalizado que muestra una alerta con el mensaje del detalle del evento.
- Disparo del evento: Activa el evento personalizado al hacer clic en un botón.
Buenas prácticas
- Prefiere
addEventListenersobre los atributosonclicken línea — mantiene el comportamiento fuera del marcado y admite múltiples manejadores. - Usa funciones regulares cuando necesites que
thishaga referencia al elemento; usa funciones flecha cuando no lo necesites, y leeevent.currentTargeten su lugar. - Elimina los listeners que ya no necesites con
removeEventListener(pasando la misma referencia de función) para evitar fugas de memoria, especialmente en aplicaciones de página única. - Adjunta un solo listener a un elemento padre en lugar de uno a cada hijo cuando manejes listas — esta técnica, llamada delegación de eventos, se basa en el bubbling de eventos.
- Limita la frecuencia de los eventos de alta frecuencia como
scrollyresizepara evitar ejecutar trabajo costoso en cada disparo; consulta optimización del rendimiento del DOM.
Conclusión
Los eventos del navegador son el puente entre lo que hace el usuario y cómo responde tu código. Los puntos clave: usa addEventListener para mayor flexibilidad, lee lo que necesites del objeto evento, llama a preventDefault() o stopPropagation() cuando debas anular el comportamiento predeterminado, y elimina los listeners que ya no necesites.
Desde aquí, explora los capítulos dedicados a eventos de ratón, eventos de teclado, manejo del envío de formularios y despacho de eventos personalizados para construir interfaces más ricas y basadas en eventos.