What are Emits?

Emits is a Vue mechanism for passing events from a child component to a parent component. In TypeScript, we add strong typing for code reliability.
Basic usage of Emits
Child component ChildComponent.vue
<template>
<button @click="handleClick">Send an event</button>
</template>
<script setup lang="ts">
// Defining types for emits
const emit = defineEmits<{
(e: 'submit', payload: string): void
(e: 'update', id: number): void
}>()
const handleClick = () => {
emit('submit', 'Data for the parent')
}
</script>
Parent component
<template>
<ChildComponent
@submit="handleSubmit"
@update="handleUpdate"
/>
</template>
<script setup lang="ts">
const handleSubmit = (payload: string) => {
console.log('Получено:', payload) // "Data for the parent"
}
const handleUpdate = (id: number) => {
console.log('ID:', id)
}
</script>
Event validation
You can add verification of the transmitted data.
<script setup lang="ts">
const emit = defineEmits<{
(e: 'submit', payload: string): boolean
}>()
const handleClick = () => {
if (!emit('submit', 'test')) {
console.error('Validation failed!')
}
}
</script>
Comprehensive TypeScript example
Child component Form Input.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>
Parent component
<template>
<FormInput
v-model="inputValue"
@submit="handleSubmit"
/>
</template>
<script setup lang="ts">
const inputValue = ref('')
const handleSubmit = () => {
alert(`Отправлено: ${inputValue.value}`)
}
</script>
Best practices
Use kebab-case in the template
<ChildComponent @custom-event="handler" />
Typing complex objects
interface User {
id: number
name: string
}
defineEmits<{
(e: 'user-update', user: User): void
}>()
Optional parameters
defineEmits<{
(e: 'event', payload?: string): void
}>()
Conclusion
- defineEmits + TypeScript = reliable event transmission
- Validation helps to debug errors
- v-model can be implemented via emits
- Interfaces make the code clearer
Homework: Basic emits
Create a CounterButton component that:
- Accepts initialValue (number) via props
- Increases the value when clicked and sends an update event with a new value.
- Use TypeScript interfaces for props and emits
<!-- CounterButton.vue -->
<script setup lang="ts">
// Your code is here
</script>
<template>
<button @click="handleClick">
{{ count }}
</button>
</template>
Check
<template>
<CounterButton
:initialValue="5"
@update="(val) => console.log(val)"
/>
</template>
When clicked, it should output to the console: 6, 7, 8…