Eventos en JavaScript
Los eventos permiten que tu página web responda a las acciones del usuario: clics, teclas, envío de formularios y mucho más.
1. ¿Qué son los eventos?
Un evento es una acción que ocurre en tu página web: hacer clic en un botón, escribir en un input, mover el ratón, etc. JavaScript puede "escuchar" estos eventos y ejecutar código cuando ocurren.
Comparación con Java: Es similar a los ActionListener o EventHandler en Java Swing/JavaFX, pero mucho más sencillo de usar.
1// Sintaxis básica2elemento.addEventListener('evento', función);3 4// Ejemplo: Click en un botón5const boton = document.querySelector('#miBoton');6 7boton.addEventListener('click', function() {8 console.log('¡Botón clickeado!');9});10 11// Con arrow function (más común)12boton.addEventListener('click', () => {13 console.log('¡Botón clickeado!');14});2. Evento: click
El evento click se dispara cuando el usuario hace clic en un elemento.
1<!DOCTYPE html>2<html>3<head>4 <style>5 .contador {6 font-size: 48px;7 text-align: center;8 margin: 20px 0;9 }10 button {11 padding: 10px 20px;12 font-size: 16px;13 cursor: pointer;14 margin: 5px;15 }16 </style>17</head>18<body>19 <div class="contador">0</div>20 <button id="incrementar">Incrementar</button>21 <button id="decrementar">Decrementar</button>22 <button id="resetear">Resetear</button>23 24 <script>25 let contador = 0;26 const display = document.querySelector('.contador');27 28 document.querySelector('#incrementar').addEventListener('click', () => {29 contador++;30 display.textContent = contador;31 });32 33 document.querySelector('#decrementar').addEventListener('click', () => {34 contador--;35 display.textContent = contador;36 });37 38 document.querySelector('#resetear').addEventListener('click', () => {39 contador = 0;40 display.textContent = contador;41 });42 </script>43</body>44</html>3. El objeto event
Cuando ocurre un evento, JavaScript crea un objeto event con información sobre lo que pasó. Puedes recibirlo como parámetro en tu función. Los eventos se pueden aplicar a cualquier elemento, incluso al body o window.
1<!DOCTYPE html>2<html>3<head>4 <style>5 body {6 height: 100vh;7 margin: 0;8 display: flex;9 justify-content: center;10 align-items: center;11 background-color: #f3f4f6;12 cursor: crosshair;13 }14 #info {15 font-size: 24px;16 text-align: center;17 padding: 20px;18 background-color: white;19 border-radius: 10px;20 box-shadow: 0 4px 6px rgba(0,0,0,0.1);21 }22 #coordenadas {23 color: #3b82f6;24 font-weight: bold;25 font-size: 32px;26 }27 </style>28</head>29<body>30 <div id="info">31 <p>Haz clic en cualquier parte de la página</p>32 <div id="coordenadas">X: 0, Y: 0</div>33 <p id="elemento"></p>34 </div>35 36 <script>37 // ⭐ Aplicar evento al BODY (elemento abstracto)38 document.body.addEventListener('click', (event) => {39 // event contiene TODA la información del evento40 const x = event.clientX;41 const y = event.clientY;42 const tipo = event.type;43 const elemento = event.target.tagName;44 45 // Mostrar información visual46 document.querySelector('#coordenadas').textContent =47 `X: ${x}, Y: ${y}`;48 49 document.querySelector('#elemento').textContent =50 `Elemento: <${elemento}>`;51 52 console.log('Tipo de evento:', tipo);53 console.log('Elemento clickeado:', elemento);54 console.log('Posición X:', x);55 console.log('Posición Y:', y);56 });57 58 // También funciona con window59 window.addEventListener('resize', (e) => {60 console.log('Ventana redimensionada:', window.innerWidth, 'x', window.innerHeight);61 });62 </script>63</body>64</html>Eventos en elementos abstractos
Puedes aplicar eventos a elementos "abstractos" como:
document.body- Todo el contenido de la páginawindow- La ventana del navegador (resize, scroll)document- El documento completo
4. Evento: input
El evento input se dispara cada vez que el usuario escribe en un campo de texto.
1<!DOCTYPE html>2<html>3<body>4 <label>Escribe tu nombre:</label>5 <input type="text" id="nombre" placeholder="Tu nombre...">6 <p id="saludo"></p>7 8 <script>9 const input = document.querySelector('#nombre');10 const saludo = document.querySelector('#saludo');11 12 input.addEventListener('input', (e) => {13 const valor = e.target.value;14 saludo.textContent = valor ? `¡Hola, ${valor}!` : '';15 });16 </script>17</body>18</html>Otros eventos de input útiles
1const input = document.querySelector('#campo');2 3// change - Se dispara cuando el input pierde foco y el valor cambió4input.addEventListener('change', (e) => {5 console.log('Valor final:', e.target.value);6});7 8// focus - Cuando el input recibe foco9input.addEventListener('focus', () => {10 console.log('Input enfocado');11});12 13// blur - Cuando el input pierde foco14input.addEventListener('blur', () => {15 console.log('Input desenfocado');16});17 18// keypress - Cuando se presiona una tecla (obsoleto, usa keydown)19input.addEventListener('keydown', (e) => {20 console.log('Tecla presionada:', e.key);21 22 // Ejemplo: Detectar Enter23 if (e.key === 'Enter') {24 console.log('¡Enter presionado!');25 }26});5. Evento: submit (formularios)
El evento submit se dispara cuando se envía un formulario. Es MUY IMPORTANTE usar preventDefault() para evitar que la página se recargue.
1<!DOCTYPE html>2<html>3<body>4 <form id="miFormulario">5 <label>Email:</label>6 <input type="email" id="email" required>7 8 <label>Password:</label>9 <input type="password" id="password" required>10 11 <button type="submit">Iniciar sesión</button>12 </form>13 14 <div id="resultado"></div>15 16 <script>17 const form = document.querySelector('#miFormulario');18 const resultado = document.querySelector('#resultado');19 20 form.addEventListener('submit', (e) => {21 // ⚠️ IMPORTANTE: Prevenir recarga de página22 e.preventDefault();23 24 // Obtener valores25 const email = document.querySelector('#email').value;26 const password = document.querySelector('#password').value;27 28 // Procesar el formulario29 console.log('Email:', email);30 console.log('Password:', password);31 32 resultado.textContent = `Formulario enviado: ${email}`;33 });34 </script>35</body>36</html>⚠️ No olvides preventDefault()
Por defecto, los formularios recargan la página al enviarse. Usa e.preventDefault() para evitarlo y manejar el envío con JavaScript.
6. Delegación de eventos
En lugar de añadir un evento a cada elemento, puedes añadirlo a un contenedor padre y usar event.target para saber qué elemento fue clickeado. Esto es más eficiente cuando tienes muchos elementos.
1<!DOCTYPE html>2<html>3<body>4 <ul id="lista">5 <li>Item 1</li>6 <li>Item 2</li>7 <li>Item 3</li>8 <li>Item 4</li>9 <li>Item 5</li>10 </ul>11 12 <script>13 // ❌ Forma ineficiente: Añadir evento a cada <li>14 // const items = document.querySelectorAll('li');15 // items.forEach(item => {16 // item.addEventListener('click', () => {17 // console.log('Clickeado:', item.textContent);18 // });19 // });20 21 // ✅ Forma eficiente: Delegación de eventos22 const lista = document.querySelector('#lista');23 24 lista.addEventListener('click', (e) => {25 // Verificar que se clickeó un <li>26 if (e.target.tagName === 'LI') {27 console.log('Clickeado:', e.target.textContent);28 e.target.style.backgroundColor = '#3b82f6';29 e.target.style.color = 'white';30 }31 });32 33 // Ventaja: Funciona incluso con elementos añadidos dinámicamente34 const nuevoItem = document.createElement('li');35 nuevoItem.textContent = 'Item 6 (añadido dinámicamente)';36 lista.append(nuevoItem);37 // ¡El evento también funciona para este nuevo elemento!38 </script>39</body>40</html>Ventajas de la delegación
- Más eficiente (un solo event listener)
- Funciona con elementos creados dinámicamente
- Usa menos memoria
7. Eliminacion-Remover eventos (elemento.removeEventListener)
1const boton = document.querySelector('#boton');2 3// Para remover un evento, necesitas una función con nombre4function manejarClick() {5 console.log('Click!');6}7 8// Añadir evento9boton.addEventListener('click', manejarClick);10 11// Remover evento12boton.removeEventListener('click', manejarClick);13 14// ❌ Esto NO funciona (funciones anónimas diferentes)15boton.addEventListener('click', () => console.log('A'));16boton.removeEventListener('click', () => console.log('A')); // No se remueve17 18// ✅ Esto SÍ funciona (misma referencia)19const handler = () => console.log('B');20boton.addEventListener('click', handler);21boton.removeEventListener('click', handler); // Se remueve correctamente8. Ejercicios Prácticos
Ejercicio 1: Validación de formulario
Crea un formulario de registro con los siguientes campos:
- Nombre (mínimo 3 caracteres)
- Email (debe contener @)
- Contraseña (mínimo 6 caracteres)
- Al enviar, valida los campos y muestra errores si hay problemas
Ver solución
1<!DOCTYPE html>2<html>3<head>4 <style>5 .error {6 color: #ef4444;7 font-size: 14px;8 margin-top: 5px;9 }10 input.invalido {11 border: 2px solid #ef4444;12 }13 .exito {14 color: #10b981;15 font-weight: bold;16 }17 </style>18</head>19<body>20 <form id="registro">21 <div>22 <label>Nombre:</label>23 <input type="text" id="nombre">24 <div class="error" id="errorNombre"></div>25 </div>26 27 <div>28 <label>Email:</label>29 <input type="email" id="email">30 <div class="error" id="errorEmail"></div>31 </div>32 33 <div>34 <label>Contraseña:</label>35 <input type="password" id="password">36 <div class="error" id="errorPassword"></div>37 </div>38 39 <button type="submit">Registrarse</button>40 </form>41 42 <div id="resultado"></div>43 44 <script>45 const form = document.querySelector('#registro');46 const nombre = document.querySelector('#nombre');47 const email = document.querySelector('#email');48 const password = document.querySelector('#password');49 50 form.addEventListener('submit', (e) => {51 e.preventDefault();52 53 // Limpiar errores previos54 document.querySelectorAll('.error').forEach(el => el.textContent = '');55 document.querySelectorAll('input').forEach(el => el.classList.remove('invalido'));56 57 let valido = true;58 59 // Validar nombre60 if (nombre.value.trim().length < 3) {61 document.querySelector('#errorNombre').textContent = 'Mínimo 3 caracteres';62 nombre.classList.add('invalido');63 valido = false;64 }65 66 // Validar email67 if (!email.value.includes('@')) {68 document.querySelector('#errorEmail').textContent = 'Email inválido';69 email.classList.add('invalido');70 valido = false;71 }72 73 // Validar contraseña74 if (password.value.length < 6) {75 document.querySelector('#errorPassword').textContent = 'Mínimo 6 caracteres';76 password.classList.add('invalido');77 valido = false;78 }79 80 // Mostrar resultado81 if (valido) {82 document.querySelector('#resultado').innerHTML =83 '<p class="exito">¡Registro exitoso!</p>';84 form.reset();85 }86 });87 </script>88</body>89</html>Ejercicio 2: Lista de tareas con eliminar
Crea una lista de tareas donde:
- Puedas añadir tareas
- Cada tarea tenga un botón "Eliminar"
- Al hacer clic en "Eliminar", se borre esa tarea
- Usa delegación de eventos
Ver solución
1<!DOCTYPE html>2<html>3<head>4 <style>5 .tarea {6 display: flex;7 justify-content: space-between;8 align-items: center;9 padding: 10px;10 margin: 5px 0;11 background-color: #f3f4f6;12 border-radius: 5px;13 }14 .btn-eliminar {15 background-color: #ef4444;16 color: white;17 border: none;18 padding: 5px 10px;19 border-radius: 3px;20 cursor: pointer;21 }22 </style>23</head>24<body>25 <input type="text" id="inputTarea" placeholder="Nueva tarea...">26 <button id="btnAgregar">Añadir</button>27 28 <ul id="listaTareas"></ul>29 30 <script>31 const input = document.querySelector('#inputTarea');32 const btnAgregar = document.querySelector('#btnAgregar');33 const lista = document.querySelector('#listaTareas');34 35 // Añadir tarea36 btnAgregar.addEventListener('click', agregarTarea);37 input.addEventListener('keypress', (e) => {38 if (e.key === 'Enter') agregarTarea();39 });40 41 function agregarTarea() {42 const texto = input.value.trim();43 if (texto === '') return;44 45 const li = document.createElement('li');46 li.classList.add('tarea');47 li.innerHTML = `48 <span>${texto}</span>49 <button class="btn-eliminar">Eliminar</button>50 `;51 52 lista.append(li);53 input.value = '';54 input.focus();55 }56 57 // Delegación de eventos para eliminar58 lista.addEventListener('click', (e) => {59 if (e.target.classList.contains('btn-eliminar')) {60 e.target.parentElement.remove();61 }62 });63 </script>64</body>65</html>Ejercicio 3: Cambiar tema (claro/oscuro)
Crea un botón que alterne entre tema claro y oscuro:
- Crea estilos para tema claro y oscuro
- Al hacer clic en el botón, cambia entre temas
- El botón debe mostrar "Tema Oscuro" o "Tema Claro" según corresponda
Ver solución
1<!DOCTYPE html>2<html>3<head>4 <style>5 body {6 transition: background-color 0.3s, color 0.3s;7 padding: 20px;8 font-family: Arial, sans-serif;9 }10 11 body.claro {12 background-color: #ffffff;13 color: #000000;14 }15 16 body.oscuro {17 background-color: #1f2937;18 color: #ffffff;19 }20 21 button {22 padding: 10px 20px;23 font-size: 16px;24 cursor: pointer;25 border-radius: 5px;26 border: 2px solid;27 }28 29 .claro button {30 background-color: #1f2937;31 color: #ffffff;32 border-color: #1f2937;33 }34 35 .oscuro button {36 background-color: #ffffff;37 color: #1f2937;38 border-color: #ffffff;39 }40 </style>41</head>42<body class="claro">43 <h1>Cambiar tema</h1>44 <p>Este es un texto de ejemplo.</p>45 <button id="btnTema">🌙 Tema Oscuro</button>46 47 <script>48 const boton = document.querySelector('#btnTema');49 const body = document.body;50 51 boton.addEventListener('click', () => {52 // Alternar clase53 if (body.classList.contains('claro')) {54 body.classList.remove('claro');55 body.classList.add('oscuro');56 boton.textContent = '☀️ Tema Claro';57 } else {58 body.classList.remove('oscuro');59 body.classList.add('claro');60 boton.textContent = '🌙 Tema Oscuro';61 }62 });63 </script>64</body>65</html>