Emits and custom events in Vue.js
What are Emits?
Emits are how child components communicate with parent components in Vue. A child emits a custom event, and the parent listens to it. This is the reverse of props (parent β child).
Basic Usage
vue
<!-- ChildComponent.vue -->
<script setup>
const emit = defineEmits(['update', 'delete'])
function handleSave() {
emit('update', { name: 'Alice', age: 25 })
}
function handleDelete() {
emit('delete')
}
</script>
<template>
<button @click="handleSave">Save</button>
<button @click="handleDelete">Delete</button>
</template>vue
<!-- ParentComponent.vue -->
<template>
<ChildComponent
@update="handleUpdate"
@delete="handleDelete"
/>
</template>
<script setup>
function handleUpdate(data: { name: string; age: number }) {
console.log('Updated:', data)
}
function handleDelete() {
console.log('Deleted!')
}
</script>TypeScript Emit Declarations
vue
<script setup lang="ts">
// Type-safe emits
const emit = defineEmits<{
update: [data: { name: string; age: number }]
delete: [id: string]
search: [query: string, page: number]
close: []
}>()
emit('update', { name: 'Alice', age: 25 }) // β
Type-checked
emit('update', 'wrong') // β Type error
emit('close') // β
No payload
</script>Emit Validation
vue
<script setup>
const emit = defineEmits({
// Validate the emitted value
update(payload: { name: string }) {
return payload.name.length > 0 // Return true if valid
},
// No validation
close: null,
})
</script>v-model with Emits
vue
<!-- CustomInput.vue -->
<script setup>
defineProps<{ modelValue: string }>()
const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
</script>
<template>
<input
:value="modelValue"
@input="emit('update:modelValue', ($event.target as HTMLInputElement).value)"
/>
</template>vue
<!-- Parent.vue -->
<template>
<!-- v-model is shorthand for :modelValue + @update:modelValue -->
<CustomInput v-model="name" />
</template>Multiple v-models
vue
<!-- UserForm.vue -->
<script setup>
defineProps<{ firstName: string; lastName: string }>()
defineEmits<{
'update:firstName': [value: string]
'update:lastName': [value: string]
}>()
</script>
<!-- Parent.vue -->
<UserForm v-model:firstName="first" v-model:lastName="last" />Props Down, Events Up
Parent
β
βββ props βββ Child (data flows DOWN)
β
βββ @events βββ Child (events flow UP)This is Vue's one-way data flow: parents pass data via props, children notify parents via emits.
Important:
Emits are the standard way for child-to-parent communication in Vue. Always declare emits with defineEmits for documentation and type safety. Use TypeScript generics for fully typed events. The v-model directive is syntactic sugar for a prop + emit pair (modelValue + update:modelValue).
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.