Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Events: v-on and modifiers

The v-on directive attaches an event handler — code that runs on a click, a key press or a form submission. It replaces addEventListener from the tutorial. The short form is usually used — @ followed by the event name.

A handler function

<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Buy bread', done: false },
  { id: 2, text: 'Call Anna', done: true },
])
 
function clearDone() {
  todos.value = todos.value.filter((todo) => !todo.done)
}
</script>
 
<template>
  <p>Tasks: {{ todos.length }}</p>
  <button @click="clearDone">Delete finished</button>
</template>

The page shows "Tasks: 2", after the click — "Tasks: 1". @click gets the function name without parentheses: Vue calls it on click.

A handler with an argument

If a function needs data, call it with parentheses right in the template:

<script setup>
import { ref } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Buy bread', done: false },
  { id: 2, text: 'Call Anna', done: false },
])
 
function toggle(todo) {
  todo.done = !todo.done
}
</script>
 
<template>
  <ul>
    <li v-for="todo in todos" :key="todo.id" @click="toggle(todo)">
      {{ todo.done ? '✓' : '○' }} {{ todo.text }}
    </li>
  </ul>
</template>

Clicking a task toggles the mark at the start of its row. For simple actions a function is optional: @click="todo.done = !todo.done" works the same.

The event object

If a handler is given without parentheses, Vue passes it the event object — the same event as in addEventListener. With parentheses, the object is available through the special $event variable:

<script setup>
function logKey(event) {
  console.log('Key pressed:', event.key)
}
</script>
 
<template>
  <input @keydown="logKey" placeholder="Press a key">
</template>

When you press keys in the field, the console prints their names: Key pressed: a, Key pressed: Enter.

Modifiers

A modifier is written after the event name with a dot and saves you from boilerplate in the handler:

ModifierWhat it does
.preventCalls event.preventDefault()
.stopCalls event.stopPropagation()
.onceThe handler fires only once
.selfOnly if the event happened on the element itself
.enter, .escOnly for the given key
<template>
  <form @submit.prevent="addTodo">
    <input @keyup.esc="clearInput">
    <button>Add</button>
  </form>
</template>

.prevent stops the form from reloading the page on submit, and .esc calls clearInput only when Escape is pressed. The addTodo and clearInput functions are declared in <script setup>.

Common mistake

In the template both @click="clearDone" and @click="clearDone()" work. The mistake is different: writing @click="toggle" for a function that needs an argument. It then receives the event object instead of the task, and todo.done turns out to be undefined. If a function needs data, pass it explicitly: @click="toggle(todo)".

Thanks for reading!

Donate to the site — we work hard for you.