Что такое Emits?

Emits — это механизм Vue для передачи событий от дочернего компонента к родительскому. В TypeScript мы добавляем строгую типизацию для надежности кода.
Базовое использование Emits
Дочерний компонент ChildComponent.vue
<template>
<button @click="handleClick">Отправить событие</button>
</template>
<script setup lang="ts">
// Определяем типы для emits
const emit = defineEmits<{
(e: 'submit', payload: string): void
(e: 'update', id: number): void
}>()
const handleClick = () => {
emit('submit', 'Данные для родителя')
}
</script>
Родительский компонент
<template>
<ChildComponent
@submit="handleSubmit"
@update="handleUpdate"
/>
</template>
<script setup lang="ts">
const handleSubmit = (payload: string) => {
console.log('Получено:', payload) // "Данные для родителя"
}
const handleUpdate = (id: number) => {
console.log('ID:', id)
}
</script>
Валидация событий
Можно добавить проверку передаваемых данных
<script setup lang="ts">
const emit = defineEmits<{
(e: 'submit', payload: string): boolean
}>()
const handleClick = () => {
if (!emit('submit', 'test')) {
console.error('Валидация не пройдена!')
}
}
</script>
Комплексный пример с TypeScript
Дочерний компонент FormInput.vue
<template>
<input
:value="modelValue"
@input="emitValue($event.target.value)"
/>
</template>
<script setup lang="ts">
interface Props {
modelValue: string
}
interface Emits {
(e: 'update:modelValue', value: string): void
(e: 'submit'): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const emitValue = (value: string) => {
emit('update:modelValue', value)
if (value.length > 5) {
emit('submit')
}
}
</script>
Родительский компонент
<template>
<FormInput
v-model="inputValue"
@submit="handleSubmit"
/>
</template>
<script setup lang="ts">
const inputValue = ref('')
const handleSubmit = () => {
alert(`Отправлено: ${inputValue.value}`)
}
</script>
Лучшие практики
Используйте kebab-case в шаблоне
<ChildComponent @custom-event="handler" />
Типизация сложных объектов
interface User {
id: number
name: string
}
defineEmits<{
(e: 'user-update', user: User): void
}>()
Опциональные параметры
defineEmits<{
(e: 'event', payload?: string): void
}>()
Заключение
- defineEmits + TypeScript = надежная передача событий
- Валидация помогает отлаживать ошибки
- v-model можно реализовать через emits
- Интерфейсы делают код понятнее
Домашнее задание: базовые emits
Создайте компонент CounterButton, который:
- Принимает initialValue (число) через props
- При клике увеличивает значение и отправляет событие update с новым значением
- Используйте TypeScript интерфейсы для props и emits
<!-- CounterButton.vue -->
<script setup lang="ts">
// Ваш код здесь
</script>
<template>
<button @click="handleClick">
{{ count }}
</button>
</template>
Проверка
<template>
<CounterButton
:initialValue="5"
@update="(val) => console.log(val)"
/>
</template>
При клике должно выводить в консоль: 6, 7, 8…