La directiva v-on (abreviada como @) es una directiva utilizada para gestionar los eventos del DOM desde los templates de Vue, haciendo más cómodo y práctico su utilización, permitiendo escribir mucho menos código. Así pues, nos ahorramos realizar .addEventListener(), y en su lugar definimos las acciones de forma mucho más directa.

Directiva v-on (Eventos en Vue)

Quizás, si nunca has utilizado eventos en Javascript, deberías echar un vistazo al siguiente artículo de la serie de componentes web nativos: Eventos en WebComponents.

¿Cómo funciona v-on?

Observa el siguiente ejemplo. Así es la forma en la que se puede definir un evento HTML de forma nativa para un evento de tipo click, utilizando el atributo HTML onclick:

<button onClick="showMessage()">Click</button>

<script>
const showMessage = () => alert("Hello!! Thanks for click me!");
</script>

Sin embargo, esta modalidad produce un acoplamiento de la función Javascript showMessage() en el HTML, de modo que si cambiaramos el nombre de la función en Javascript (o algo similar), dependeríamos de ese fragmento HTML (que muchas veces en la práctica incluso está en archivos diferentes). Además, la función showMessage() debería estar en un ámbito global.

Para evitar estos inconvenientes, podríamos modificarlo a algo parecido a esto:

<button class="alert">Click</button>

<script>
const button = document.querySelector("button.alert");
button.addEventListener("click", () => {
  alert("Hello!! Thanks for click me!");
});
</script>

En este caso, el peso de la lógica recae íntegramente en la parte Javascript, simplemente utilizamos el nombre de un id o class (un selector CSS) para hacer referencia a él. También hay acomplamiento, pero es menor y dependerá de lo consistente que sea nuestro selector respecto a ello.

En Vue, la forma de realizar esto, se reduce al siguiente código:

<template>
  <div>
    <button v-on:click="showMessage">Click</button>
    <button @click="showMessage">Click</button> <!-- Equivalente al anterior -->
    <button @[event]="showMessage">Click</button> <!-- Evento dinámico -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      event: "click"
    }
  },
  methods: {
    showMessage() {
      alert("Hello!! Thanks for click me!");
    }
  }
}
</script>

Observa que la directiva v-on está usando el evento click, pero podría ser otro evento como mousedown, mouseup, dblclick u otro. Como se puede ver justo debajo, la forma abreviada es reemplazar v-on: por @.

Por último, observa que entre corchetes hacemos referencia a una variable event que tenemos en data. Dicha variable contiene el tipo de evento que queremos ejecutar, por lo que podemos hacerlo de forma dinámica mediante este mecanismo.

En todos los casos, el valor que le damos a la directiva v-on es el nombre del método a ejecutar, que se encuentra en la opción methods de Vue.

Controlando varios eventos

En el caso de que estemos buscando controlar varios eventos y organizarlo todo en un mismo lugar, podemos crear un objeto en nuestro apartado data de Vue, y en su interior colocar las funciones específicas, utilizando la key de la propiedad como nombre del evento en cuestión:

<template>
  <div>
    <button v-on="handleEvent">Click me!</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      handleEvent: {
        click: () => alert("¡Has hecho click!"),
        mouseleave: () => alert("¡Has sacado el ratón del botón!"),
        mousewheel: (event) => console.log("¡Has movido la rueda del ratón!", event.deltaY)
      },
    }
  }
}
</script>

En este ejemplo estamos controlando tres tipos de evento: click (hacer click en un elemento), mouseleave (sacar el cursor del ratón de un elemento) y mousewheel (mover la rueda del ratón en un elemento). Cada una de ellas ejecuta una función específica, donde podría estar la lógica relacionada con ese evento.

Observa el último caso, donde he añadido un parámetro event en la función ejecutada en el evento. Dicho parámetro recogerá los datos específicos del evento, donde por ejemplo, event.deltaY nos ofrece la cantidad de píxels desplazados (en el eje Y) al mover la rueda del ratón. Cada evento tiene sus propias características y es algo que es propio de Javascript nativo, no es una característica de Vue.

Modificadores de v-on

Al igual que otras directivas, es posible añadir modificadores después del tipo del evento y así modificar el comportamiento de la directiva. Algunos de los modificadores que podríamos utilizar, son los siguientes:

Modificador Descripción
.stop Llama al método event.stopPropagation() para parar la propagación del evento.
.prevent Llama al método event.preventDefault() para evitar el comportamiento por defecto.
.capture Utiliza el modo capture del .addEventListener().
.self Sólo se dispara si el evento es generado desde el propio elemento.
.once Sólo se dispara la primera vez. Equivalente al parámetro { once: true }.
.passive Realiza una escucha pasiva. Equivalente al parámetro { passive: true }.

Recuerda que dichos modificadores lo que hacen es alterar el comportamiento normal del evento con alguna característica concreta. Veamos un ejemplo donde se aplican:

<template>
  <div>
    <button v-on:click.once="showMessage">Avisarme (solo una vez)</button>
    <!-- Equivalente al anterior (y preferido): -->
    <button @click.once="showMessage">Avisarme (solo una vez)</button>
  </div>
</template>

El modificador .once hace que el evento sólo se lleve a cabo la primera vez que se hace click. Cuando se ejecuta el método asociado, el evento no vuelve a ejecutarse (ya no estará escuchando).

Modificadores de teclas (KeyAlias)

Aunque no fueron mencionados en la tabla anterior, existen una serie de modificadores para activar eventos si se realizan junto a ciertas pulsaciones de teclado o de ratón. Por ejemplo, utilizando el modificador .ctrl en un evento @click, se ejecutará el método sólo si el usuario hace click de ratón teniendo pulsada la tecla CTRL.

De la misma forma se pueden usar modificadores como .right en un evento @click, de modo que sólo se ejecutará el método si el usuario hace click con botón derecho del ratón.

La lista de modificadores de esta categoría son los siguientes:

En esta lista se incluyen sólo los modificadores de las teclas más comunes. Si te interesa una tecla que no está en la lista, puedes pulsar en el siguiente cuadro blanco y al pulsar la tecla que te interesa, te aparecerá su alias y su código:

Por ejemplo, si pulsamos la tecla BLOQ MAYUS veremos que aparece CapsLock (20). En Vue el modificador para esta tecla es caps-lock (su versión en kebab case). Recuerda que el código numérico no se debe utilizar (usar códigos numéricos está marcado como obsoleto):

<template>
  <div>
    <input @keyup.20="showMessage">         <!-- No usar. Deprecated -->
    <input @keyup.CapsLock="showMessage">   <!-- Incorrecto. No es kebab-case -->
    <input @keyup.caps-lock="showMessage">  <!-- Correcto -->
  </div>
</template>

Consejo: Si usas VSCode como editor, la extensión Vetur te autocompleta y convierte los modificadores con código numérico, en modificadores con el alias adecuado.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev