Send Messages Up to the Parent
Custom Events With defineEmits
defineEmits declares the events a component can emit so parents can listen with @event handlers — and TypeScript validates the payloads.
What you'll learn
- Declare emits with defineEmits
- Emit with the returned function
- Type emits with TypeScript
Data flows down via props; events flow up via emits. defineEmits declares the events a child can fire, the parent listens with @event="handler", and TypeScript validates the payloads.
Declare With Runtime Options
<script setup>
const emit = defineEmits(['saved', 'cancel'])
function onSubmit() {
emit('saved', { id: 1, name: 'Ada' })
}
</script>
<template>
<button @click="onSubmit">Save</button>
<button @click="emit('cancel')">Cancel</button>
</template> TypeScript Declaration
Pass a type with event names mapped to argument tuples:
<script setup lang="ts">
interface User { id: number; name: string }
const emit = defineEmits<{
saved: [user: User]
cancel: []
remove: [id: number, soft: boolean]
}>()
const user: User = { id: 1, name: 'Ada' }
emit('saved', user)
emit('remove', 1, true)
</script> The compiler now refuses emit('saved') with no argument or emit('saved', 123).
Listening in the Parent
<template>
<UserForm
@saved="onSaved"
@cancel="show = false"
@remove="onRemove"
/>
</template>
<script setup lang="ts">
const onSaved = (user: User) => console.log('saved', user)
const onRemove = (id: number, soft: boolean) => console.log(id, soft)
</script> v-model — A Special Emit
v-model on a custom component is built on emits — it listens for update:modelValue. We cover this with defineModel later in the course.