События: v-on и модификаторы
Директива v-on назначает обработчик события — код, который выполнится при клике, нажатии клавиши или отправке формы. Это замена addEventListener из учебника. Обычно пишут короткую форму — @ и имя события.
Обработчик-функция
<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
const todos = ref([
{ id: 1, text: 'Купить хлеб', done: false },
{ id: 2, text: 'Позвонить Анне', done: true },
])
function clearDone() {
todos.value = todos.value.filter((todo) => !todo.done)
}
</script>
<template>
<p>Задач: {{ todos.length }}</p>
<button @click="clearDone">Удалить выполненные</button>
</template>Страница показывает «Задач: 2», после клика — «Задач: 1». В @click передано имя функции без скобок: Vue сам вызовет её при клике.
Обработчик с аргументом
Если функции нужны данные, её вызывают со скобками прямо в шаблоне:
<script setup>
import { ref } from 'vue'
const todos = ref([
{ id: 1, text: 'Купить хлеб', done: false },
{ id: 2, text: 'Позвонить Анне', 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>Клик по задаче переключает значок у неё в начале строки. Для простых действий функция не обязательна: @click="todo.done = !todo.done" сработает так же.
Объект события
Если обработчик указан без скобок, Vue передаёт ему объект события — тот же event, что и в addEventListener. Если со скобками, объект доступен через специальную переменную $event:
<script setup>
function logKey(event) {
console.log('Нажата клавиша:', event.key)
}
</script>
<template>
<input @keydown="logKey" placeholder="Нажмите клавишу">
</template>При нажатии клавиш в поле консоль показывает их названия: Нажата клавиша: a, Нажата клавиша: Enter.
Модификаторы
Модификатор пишется через точку после имени события и избавляет от служебного кода в обработчике:
| Модификатор | Что делает |
|---|---|
.prevent | Вызывает event.preventDefault() |
.stop | Вызывает event.stopPropagation() |
.once | Обработчик сработает один раз |
.self | Только если событие произошло на самом элементе |
.enter, .esc | Только для указанной клавиши |
<template>
<form @submit.prevent="addTodo">
<input @keyup.esc="clearInput">
<button>Добавить</button>
</form>
</template>.prevent не даёт форме перезагрузить страницу при отправке, а .esc вызывает clearInput только при нажатии Escape. Функции addTodo и clearInput объявляются в <script setup>.
Частая ошибка
В шаблоне обе записи @click="clearDone" и @click="clearDone()" работают. Ошибка в другом: написать @click="toggle" для функции, которой нужен аргумент. Тогда вместо задачи она получит объект события, и todo.done окажется undefined. Если функции нужны данные — передавайте их явно: @click="toggle(todo)".