Skip to main content
Practice Problems

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 ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems