ManzDev
Perfil de Manz Dashboard de actividad
HTML5 Etiquetas HTML
CSS CSS vanilla
PostCSS Transformador CSS
Javascript Javascript ES2020+
NPM Node Package Manager
WebComponents Componentes web
Terminal Terminal de GNU/Linux
VueJS Framework VueJS 3
Automatizadores Empaquetadores Javascript
Dibujando con CSS ¡Dibujos hechos con sólo CSS!
Experimentos con Javascript ¡Experimentos con Javascript!

Eventos en Javascript

En Javascript existe un concepto llamado evento, que no es más que una notificación de que alguna característica interesante acaba de ocurrir. Dichas características pueden ser de múltiples tipos y muy variadas: desde un click de ratón hasta la pulsación de una tecla de teclado o la reproducción de un audio o video, entre muchas otras.

Como desarrolladores, nuestro objetivo es preparar el código para que cuando ocurra un evento con ciertas características, se ejecute un código asociado. Para ello, podemos gestionar los eventos de varias formas (veamos un ejemplo con el evento click):

Ejemplo Descripción
<button onClick="..."></button> Mediante un atributo HTML precedido de on que llama a la función.
.onclick = ... Mediante propiedades precedidas de on que contienen una función.
.addEventListener("click", ...) Mediante la escucha de eventos a través de listeners.

Cada una de estas opciones se puede utilizar para gestionar eventos en Javascript de forma equivalente, pero cada forma tiene sus ventajas y sus desventajas. Veamos detalladamente sus características.

Eventos mediante HTML

Probablemente, la forma más básica y sencilla es la de crear Eventos HTML a través de un atributo HTML en una etiqueta, como por ejemplo <button>. Se trata de una aproximación simple y sencilla, que para casos muy básicos puede ser más que suficiente:

<button onClick="alert('Hello!')">Saludar</button>

En este ejemplo, cuando el usuario haga click con el ratón en el botón Saludar, se dispara el evento click sobre ese elemento HTML, y al tener un atributo onClick (cuando hagas click), se ejecutará el código que tenemos en el valor de dicho atributo, en este caso un alert(), que no es más que un mensaje emergente con el texto indicado.

Sin embargo, crear eventos mediante HTML aunque es buen punto de partida inicial, tiene ciertas desventajas:

  1. En primer lugar, estamos mezclando código de marcado HTML con código Javascript, cuando lo ideal sería tenerlo bien separado.

  2. En segundo lugar, si el código del onClick es muy extenso, perjudica la legibilidad del mismo.

  3. En tercer lugar, en el onClick podríamos hacer referencia al nombre de una función Javascript, solucionando el punto 2, pero seguiríamos con el mismo problema del punto 1. Además, a la larga, sería más complejo de mantener porque existe una dependencia del nombre de la función.

Eventos mediante propiedades

Esta opción se realiza desde Javascript. La idea es la misma que en la anterior, pero haciendo uso de una propiedad especial precedida por on a la que asignaremos la función con el código deseado.

const button = document.querySelector("button");
button.onclick = function() {
  alert("Hello!");
}

Observa que en este caso, lo que hacemos es asignar la función (con el código que queremos ejecutar cuando ocurra el evento) a la propiedad .onclick del elemento en cuestión (en nuestro caso, el botón que hemos seleccionado previamente).

Ten en cuenta que los eventos como .onclick siempre van en minúsculas, ya que se trata de una propiedad Javascript y es sensible a mayúsculas y minúsculas.

Eventos mediante listeners

Quizás, la forma más interesante y versátil de gestionar los eventos de Javascript sea utilizando el método .addEventListener(). Este método pone en escucha al elemento, para que cuando se dispare el evento indicado en el del primer parámetro, se ejecute la función indicada en el segundo parámetro:

Método Descripción
.addEventListener(event,func) Añade una función al evento.
.addEventListener(event,func,options) Idem, con opciones.
.removeEventListener(event,func) Elimina una función del evento.

Veamos un ejemplo sencillo del método .addEventListener() en acción:

const button = document.querySelector("button");
button.addEventListener("click", function() {
  alert("Hello!");
});

Es posible que veas mucho más organizado esto, si sacamos la función y la guardamos en una constante previamente, para luego hacer referencia a ella desde el .addEventListener():

const button = document.querySelector("button");
const action = function() {
  alert("Hello!");
};
button.addEventListener("click", action);

Dicho método .addEventListener() permite asociar múltiples funciones a un mismo evento, cosa que aunque no es imposible, es menos sencillo e intuitivo en las modalidades anteriores. Además, también es posible eliminar un listener previamente añadido, haciendo uso del método .removeEventListener() y teniendo la función externalizada en una constante:

const button = document.querySelector("button");
const funcName = function() {
  alert("Hello!");
};

button.addEventListener("click", funcName);       // Add listener
button.removeEventListener("click", funcName);    // Delete listener

Ten en cuenta que es posible eliminar el listener del evento porque hemos guardado en una constante la función, y tanto en .addEventListener() como en .removeEventListener() estamos haciendo referencia a la misma función. Si en lugar de esto, añadieramos la función literalmente, aunque hagan lo mismo, serían funciones diferentes y no realizaría lo que esperamos.

El objeto event

En algunos casos, nos puede interesar profundizar en detalles relacionados con el evento. Por ejemplo, si estamos escuchando un evento de click de ratón, nos puede interesar saber con que botón del ratón se ha hecho click, o en que punto concreto de la pantalla. Estos detalles son posibles obtenerlos a través del objeto event.

En los ejemplos anteriores, la función (callback) que ejecuta la acción al dispararse el evento no tiene parámetros. Sin embargo, podemos indicarle un nombre a un primer parámetro, que será el que contendrá la información del evento:

const button = document.querySelector("button");
button.addEventListener("click", (event) => console.log(event));

Si hacemos esto, el objeto event contendrá lo siguiente:

// Objeto MouseEvent
{
  altKey: false,      // ¿La tecla ALT estaba presionada?
  clientX: 43,        // Posición en eje X donde se hizo click
  clientY: 16,        // Posición en eje Y donde se hizo click
  ctrlKey: false,     // ¿La tecla CTRL estaba presionada?
  detail: 1,          // Contador de veces que se ha hecho click
  ...                 // Otros...
}

En este caso, se trata de un objeto MouseEvent porque el evento que estamos escuchando es un evento de ratón. Sin embargo, si utilizaramos otro evento, probablemente tendríamos un objeto diferente.

Opciones de addEventListener

Al utilizar el método .addEventListener(), su tercer parámetro es un opcional, en el cual podemos indicar alguna de las siguientes opciones para modificar alguna característica de los listeners que escuchan un evento:

Opción Descripción
capture El evento se dispara al inicio (capture), en lugar de al final (bubble).
once Sólo ejecuta la función la primera vez. Luego, elimina listener.
passive La función nunca llama a .preventDefault() (mejora rendimiento).

En primer lugar, la opción capture nos permite modificar la modalidad en la que escuchará el evento (capture/bubbles, ver más adelante). Esto, básicamente, lo que hace es modificar en que momento se procesa el evento.

En segundo lugar, la opción once nos permite indicar que el evento se procesará solo la primera vez. Internamente, lo que hace es ejecutarse la primera vez y llamar al .removeEventListener(), eliminando el listener una vez ha sido ejecutado por primera vez.

En tercer y último lugar, la opción passive nos permite crear un evento pasivo en el que indicamos que nunca llamaremos al método .preventDefault() para alterar el funcionamiento del evento. Esto puede ser muy interesante en temas de rendimiento (por ejemplo, al hacer scroll en una página), ya que los eventos pasivos son mucho menos costosos.

Manz
Publicado por Manz

Docente, divulgador informático y Streamer de código. Amante del CSS y de la plataforma web en general. Autor de Emezeta.com tiempo atrás. Ha trabajado como profesor en la Universidad de La Laguna y es director del curso de Programación web FullStack y FrontEnd de EOI en Tenerife. En sus ratos libres, busca GIF de gatos en Internet.