Vue

Обработка событий

Форма оформления заказа отправляется по кнопке, но при каждом сабмите страница перезагружается и теряет введённые данные - браузер по умолчанию делает GET-запрос на сабмит формы. Рядом модальное окно закрывается по клику на фон, но клик внутри окна тоже закрывает его, потому что событие всплывает наружу. Оба бага решаются не кодом в обработчике, а одним словом-модификатором в шаблоне: .prevent отменяет действие браузера, .self ловит клик только по самому фону. Vue выносит эту рутину из тела функции в декларативную запись.

  • Отмена перезагрузки страницы при сабмите формы через @submit.prevent
  • Закрытие модального окна кликом по затемнению через @click.self, чтобы клик внутри не закрывал его
  • Горячие клавиши: отправка комментария по Ctrl+Enter через @keyup.enter с модификатором
  • Остановка всплытия клика по кнопке внутри кликабельной карточки через @click.stop

Предварительные знания

  • Шаблонный синтаксис и привязка атрибутов
  • Понимание, что такое DOM-событие (клик, ввод, нажатие клавиши)
  • Объявление функций в script setup

v-on и сокращение @

Директива v-on привязывает обработчик к событию. Полная форма v-on:click, короткая - @click, и в коде почти всегда пишут короткую. Слушать можно любое событие DOM (click, input, keyup, submit) и любое пользовательское событие компонента. Значением может быть имя метода, инлайн-выражение или вызов метода с аргументами.

Когда обработчик указан именем метода (@click="onClick"), Vue сам передаёт в него нативное событие первым аргументом. Когда указан вызов (@click="greet('Anna')"), событие не передаётся автоматически - для доступа к нему нужен токен `$event`.

Имя метода без скобок - это ссылка на функцию, Vue вызовет её сам и передаст событие. Имя со скобками - это уже вызов, который выполнится при срабатывании события. Путаница между этими формами - частая причина того, что обработчик срабатывает сразу при рендере.

Чем отличается @click="onClick" от @click="onClick()"?

Инлайн-обработчик, метод и `$event`

Инлайн-обработчик уместен для короткого выражения прямо в шаблоне: @click="count++". Когда логики больше одной строки, её выносят в метод, чтобы шаблон оставался читаемым. Если в инлайн-обработчике нужно само событие (например, прочитать введённое значение), используют специальный токен `$event` - это ссылка на нативное DOM-событие.

  • Инлайн-обработчик — Короткое выражение в шаблоне. Доступ к событию через токен `$event`. Подходит для одной операции
  • Метод — Функция в script setup. Событие приходит аргументом автоматически. Подходит для логики из нескольких шагов

`$event` доступен по имени только внутри инлайн-обработчика в шаблоне. В методе-обработчике такого имени нет: событие приходит первым аргументом функции.

Как в инлайн-обработчике получить доступ к нативному DOM-событию?

Модификаторы событий

Часто в обработчике первым делом вызывают event.preventDefault() или event.stopPropagation(). Vue выносит эту рутину в модификаторы - суффиксы после имени события. @submit.prevent отменяет действие браузера, @click.stop останавливает всплытие, @click.self срабатывает только если кликнули по самому элементу, а не по потомку, @click.once отрабатывает один раз и снимается.

МодификаторЭквивалент в кодеКогда применяют
.preventevent.preventDefault()Сабмит формы, клик по ссылке без перехода
.stopevent.stopPropagation()Кнопка внутри кликабельного контейнера
.selfif (event.target === event.currentTarget)Клик по фону модалки, но не по её содержимому
.onceснимает слушатель после первого вызоваОдноразовое действие, например приветствие

Модификаторы можно соединять цепочкой: @click.stop.prevent отменит и всплытие, и действие по умолчанию. Порядок имеет значение - модификаторы применяются слева направо в порядке записи.

Модальное окно нужно закрывать только при клике по затемняющему фону, но не при клике по самому окну внутри него. Какой модификатор решает это?

Модификаторы клавиш

Для событий клавиатуры Vue даёт модификаторы клавиш: вместо ручной проверки event.key пишут @keyup.enter, и обработчик сработает только на Enter. Доступны имена @keyup.esc, @keyup.tab, @keyup.delete, @keyup.space и другие. Модификаторы-клавиши-управления (.ctrl, .shift, .alt, .meta) комбинируются с обычными для горячих сочетаний.

Сочетание @keyup.ctrl.enter сработает только при нажатом Ctrl и одновременном Enter - типичный паттерн отправки сообщения в чатах вроде Slack. Без модификаторов пришлось бы вручную сверять event.ctrlKey и event.key в теле функции.

Имена модификаторов соответствуют значениям event.key, приведённым к kebab-case: PageDown становится .page-down, ArrowUp - .up. Это убирает зависимость от устаревшего числового keyCode и делает шаблон самодокументируемым.

Что даёт запись @keyup.ctrl.enter="send" по сравнению с обычным @keyup="send"?

Связь с другими темами

Обработка событий - база интерактивности, на которую опираются формы и списки:

  • Формы и v-model — v-model - сахар над привязкой значения и слушателем события input, разобранного здесь
  • Условия и списки — Обработчик вешают на каждый элемент v-for, передавая ему данные конкретной строки

Итог

  • v-on:click (сокращённо @click) привязывает обработчик к событию DOM или компонента
  • Инлайн-обработчик пишут для коротких выражений; метод - когда логики больше одной строки
  • В инлайн-обработчике доступен токен `$event` - нативное событие, из которого читают target и value
  • Модификаторы событий (.prevent, .stop, .self, .once) выносят preventDefault, stopPropagation и проверки из тела функции
  • Модификаторы клавиш (.enter, .esc, .ctrl) фильтруют срабатывание по нажатой клавише без ручной проверки keyCode

Связанные уроки

  • vue-15-forms-vmodel — v-model на input под капотом слушает событие input через тот же механизм v-on, разобранный здесь
  • vue-13-conditional-list — Обработчик действия часто вешают на каждый элемент списка из v-for, передавая в него данные строки
Обработка событий

0

1

Войти