Vue Custom Events: Child-to-Parent Communication
Think of $emit as a child component sending a flare up to its parent. It's how children report actions upwards, reversing the top-down flow of props. Use it to trigger parent state changes, like closing a modal. The footgun: events don't bubble.
Why it exists
Vue's component architecture is based on a parent-to-child data flow using props. But what happens when a child needs to tell the parent something, like "the user clicked me"? Custom events solve this by providing a dedicated channel for child-to-parent communication, completing the component communication loop.
The mental model
An event emission is like a child component raising its hand and shouting a specific phrase (the event name) that only its direct parent is listening for. The parent can choose to react to that phrase. The child can also hand the parent an object (the payload) when it raises its hand, passing data along with the signal.
How it works
A child component calls the built-in emit method, providing an event name and an optional payload. For example, this.emit('update-status', 'completed'). The parent component uses the v-on directive (shorthand @) to listen for that specific event name on the child's tag, like <ChildComponent @update-status="handleStatusUpdate">. The handleStatusUpdate method in the parent will then be called, receiving 'completed' as its first argument. Vue automatically transforms camelCase event names (updateStatus) into kebab-case listeners (@update-status) in templates.
When to use it
Use custom events whenever a child component needs to inform its parent about an internal action or state change that the parent needs to know about. This is common for custom form inputs, buttons that trigger parent actions, or components like modals that need to be closed by the parent. It keeps the child encapsulated and the parent in control of the application state.
When not to use it
Avoid using $emit for communication between sibling components or deeply nested components. Events only travel one level up to the direct parent; they do not bubble like native DOM events. For cross-component communication that isn't strictly parent-child, a global state management library like Pinia is the correct tool.
One canonical example
A child component, CustomButton.vue, has a button. When clicked, it emits an event to signal this action and passes a value. The child code is <button @click="$emit('increaseBy', 5)">Increase by 5</button>. The parent listens with <CustomButton @increase-by="(amount) => total += amount" />. Clicking the button in the child tells the parent to execute its inline function, which increments the parent's total data property by 5. The child decides the value, but the parent owns the state.
Interview question
What is the primary purpose of using a custom event ($emit) in a Vue component?
- a.To enable communication between two sibling components.
- b.To trigger a global state change accessible by any component in the application.
- c.To allow a child component to send data or signals to its direct parent.Correct
- d.To pass data from a parent component down to its child components.
Why? this is the answer
The card explicitly states that custom events provide a "dedicated channel for child-to-parent communication" and that "events only travel one level up to the direct parent." Option A is wrong because the card advises against using $emit for sibling communication.
Just read this? Test yourself on what you have been reading.
Read the original → vuejs.org
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on vue — each one lists the topics its interview covers.
See open roles