In Vue.js, emit is a function that allows a child component to send a custom event to its parent component.

While props are the most common way to pass data from a parent component to a child, events are the most common way for communication in the opposite direction.
- ▲ Props: Allow downward data flow (from parent to child)
- ▼ Events: Allow upward data flow (from child to parent)
Furthermore, the emitted event can carry associated data, allowing the parent to react and perform actions based on what happens in the child.
This design pattern enables unidirectional data flow and is common in many modern Vue.js frameworks.
How to Use emit
In Vue.js we can declare the events a component can emit in several ways. The most common is using the defineEmits() function:
<script setup>
// We define the events that this component can emit
const emit = defineEmits(['update', 'delete', 'select'])
// Now we can use the emit function in our component
function handleClick() {
emit('update', { id: 1, value: 'new value' })
}
</script>
- defineEmits: It’s a function that allows us to declare the events the component can emit.
- emit: It’s a function that receives two arguments:
- The event name (as a string)
- The data we want to send to the parent component (optional)
The defineEmits function returns an emit function configured with the events we want, which we can then use in our code.
Example of emit
Let’s see it better with a simple example.
- We create a child component that emits an event when a button is clicked.
- The parent component will listen for this event and display a message in the console.
<template>
<button @click="handleClick">Click me</button>
</template>
<script setup>
const emit = defineEmits(['button-clicked']);
const handleClick = () => {
emit('button-clicked', { message: 'The button was clicked' });
};
</script>
handleClick: It’s a function that runs when the user clicks the button.emit('button-clicked', { message: '...' }): Emits an event calledbutton-clickedwith an object containing a message.
<template>
<div>
<ChildComponent @button-clicked="handleClick" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const handleClick = (data) => {
console.log('Event received:', data.message);
};
</script>
@button-clicked="handleClick": Listens for thebutton-clickedevent emitted by the child component and executes thehandleClickfunction.handleClick: Receives the data sent by the child and displays it in the console.
Event Validation with defineEmits
We can also use a more detailed syntax to validate the type of data being emitted:
<!-- ChildComponent.vue -->
<template>
<button @click="handleClick">Click me</button>
</template>
<script setup>
const emit = defineEmits({
// Validate that the 'button-clicked' event receives an object with a message
'button-clicked': (payload) => {
return payload.message && typeof payload.message === 'string';
},
});
const handleClick = () => {
emit('button-clicked', { message: 'The button was clicked' });
};
</script>
defineEmits: Defines and validates the events the component can emit.- Validation: Ensures the event payload meets certain conditions.
Bidirectional Communication with v-model and emit
Custom events are the foundation of the v-model directive in custom components.
We can implement components that support v-model by emitting the update:modelValue event:
<template>
<input :value="modelValue" @input="handleInput" />
</template>
<script setup>
defineProps({
modelValue: {
type: String,
required: true,
},
});
const emit = defineEmits(['update:modelValue']);
const handleInput = (event) => {
emit('update:modelValue', event.target.value);
};
</script>
modelValue: It’s the prop that receives the current value.emit('update:modelValue', ...): Emits an event to update the value in the parent component.
<template>
<div>
<CustomInput v-model="text" />
<p>Entered text: {{ text }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import CustomInput from './CustomInput.vue';
const text = ref('');
</script>
v-model="text": Binds the input value to thetextvariable in the parent component.
Internally, v-model uses emit to notify changes to the parent component
