Custom Events (emit)
Communicate from a child component back to its parent using defineEmits and the emit function.
Declaring and Emitting an Event
A component declares the custom events it can emit with defineEmits, then calls the returned emit function to actually fire one.
<!-- LikeButton.vue --><script setup>const emit = defineEmits(['liked']);
function handleClick() { emit('liked');}</script>
<template> <button @click="handleClick">👍 Like</button></template>Listening for the Event
A parent listens for a custom event using the same @ syntax as a native DOM event.
<script setup>import LikeButton from './LikeButton.vue';
function handleLike() { console.log('The post was liked!');}</script>
<template> <LikeButton @liked="handleLike" /></template>Passing Data with an Event
Any extra arguments passed to emit() become arguments to the parent's handler.
<!-- Child --><script setup>const emit = defineEmits(['update-quantity']);
function increase() { emit('update-quantity', 1);}</script><!-- Parent --><script setup>function handleQuantityChange(amount) { quantity.value += amount;}</script>
<template> <QuantityStepper @update-quantity="handleQuantityChange" /></template>v-model on a Custom Component
Combining a modelValue prop with an update:modelValue emit lets a custom component support v-model exactly like a native input — this is the standard pattern for building reusable form controls.
<!-- CustomInput.vue --><script setup>defineProps(['modelValue']);defineEmits(['update:modelValue']);</script>
<template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /></template><!-- Parent --><script setup>import { ref } from 'vue';import CustomInput from './CustomInput.vue';const search = ref('');</script>
<template> <CustomInput v-model="search" /></template>Common Beginner Mistakes
Vue will still work without it, but you lose validation and the clear, self-documenting contract of what events a component can fire.
emit() has no return value — communication is one-directional (child to parent); to get a "response" back down, the parent updates a prop.
FAQs
Yes — defineEmits also accepts an object form with validator functions per event, similar to prop validation.
It's Vue's required naming convention for v-model to work on a custom component — v-model="x" expands to :model-value="x" plus @update:model-value.
Summary
Props flow down, and custom events flow up — together they form the complete communication channel between parent and child. Next, you'll learn slots, for passing markup (not just data) into a child.