События во Vue 3 и кастомные события с defineEmits

🧩 1. Что такое события во Vue 3

Vue 3 позволяет легко реагировать на действия пользователя с помощью директивы v-on, сокращённо — @.

Например:

<template>
  <button @click="sayHello">Нажми меня</button>
</template>

<script setup>
function sayHello() {
  alert('Привет, Vue!')
}
</script>

🧠 Пояснение:

  • @click — слушатель события click.

  • Можно использовать любые DOM-события:

    • @input — при вводе текста,

    • @change — при изменении значения,

    • @submit — при отправке формы,

    • @keydown / @keyup — при работе с клавиатурой.

💡 2. Пример: работа с пользовательским вводом

<template>
  <div>
    <input @input="updateName" placeholder="Введите имя" />
    <p>Привет, {{ name || 'гость' }}!</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const name = ref('')

function updateName(event) {
  name.value = event.target.value
}
</script>

🧩 Разбор:

  • @input отслеживает каждое изменение в поле ввода.

  • Через event.target.value мы получаем новое значение.

  • Vue автоматически обновляет шаблон при изменении реактивной переменной.

⚡ 3. Кастомные события: defineEmits

Иногда нужно, чтобы дочерний компонент сообщил родителю, что что-то произошло — например, кнопка нажата или значение изменилось.
Для этого во Vue используется defineEmits().

🔹 Дочерний компонент — CounterButton.vue

<script setup>
const emit = defineEmits(['increment'])

let count = 0

function add() {
  count++
  emit('increment', count) // отправляем событие родителю
}
</script>

<template>
  <button @click="add">Добавить ({{ count }})</button>
</template>

<style scoped>
button {
  padding: 8px 16px;
  background: #42b883;
  border: none;
  border-radius: 8px;
  color: white;
  font-weight: 600;
  cursor: pointer;
}
button:hover {
  background: #2a8b68;
}
</style>

🧠 Что происходит:

  • defineEmits(['increment']) сообщает Vue, что этот компонент может генерировать событие increment.

  • emit('increment', count) отправляет событие с аргументом count.

🔹 Родительский компонент — App.vue

<script setup>
import CounterButton from './components/CounterButton.vue'
import { ref } from 'vue'

const total = ref(0)

function handleIncrement(value) {
  total.value = value
}
</script>

<template>
  <h2>События и defineEmits во Vue 3</h2>
  <CounterButton @increment="handleIncrement" />
  <p>Общее значение: {{ total }}</p>
</template>

🧩 Разбор:

  • Родитель подписывается на событие через @increment.

  • При каждом вызове emit('increment', count) родитель получает новое значение и обновляет интерфейс.

🔒 4. Валидация событий

Vue 3 позволяет проверять корректность данных, которые отправляются с событием.
Это особенно полезно в крупных проектах.

<script setup>
const emit = defineEmits({
  increment: (value) => typeof value === 'number' && value >= 0
})

let count = 0

function add() {
  count++
  emit('increment', count) // если value не число — Vue выдаст предупреждение в консоли
}
</script>

🧠 Пояснение:

  • Событие increment считается корректным только если аргумент — число ≥ 0.

  • Если условие не выполняется, Vue покажет предупреждение в консоли во время разработки.

📘 5. Что получится на экране

События и defineEmits во Vue 3

[Добавить (0)]
Общее значение: 0

(нажатие на кнопку)
[Добавить (1)]
Общее значение: 1