Emitting Events
Props only flow one direction, down from parent to child — so when a child needs to tell its parent something happened, it emits a custom event instead, and the parent listens for it the same way it'd listen for a native click.
Emitting a custom event from a child
this.$emit(eventName, payload) fires a named event that the parent can listen for with the same @ syntax used for native DOM events:
app.component('like-button', {
data() {
return { liked: false }
},
methods: {
toggleLike() {
this.liked = !this.liked
this.$emit('like-changed', this.liked)
}
},
template: `<button @click="toggleLike">{{ liked ? 'Liked' : 'Like' }}</button>`
})
<like-button @like-changed="handleLikeChanged"></like-button>
methods: {
handleLikeChanged(isLiked) {
console.log('Like status is now:', isLiked)
}
}
Like status is now: true
The child never touches the parent's data directly — it just announces "something happened, here's the new value," and the parent decides what to do with that information. This keeps the child reusable: it works the same way no matter what parent uses it, or what that parent does in response.
Declaring emitted events
Just like props, it's good practice to declare which events a component can emit, using the emits option — this documents the component's public interface and lets Vue warn about typos:
app.component('like-button', {
emits: ['like-changed'],
// ...rest unchanged
})