We can emit events with Vue. Events are emitted by child components and are listened to by their parent components.
Emitted can have data that’s sent along with the event emission.
In this article, we’ll look at how to emit custom Vue events with $emit
and listen to them in the parent component.
We can emit events in our child component and use the listen to the event and use the emitted data as follows:
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Foo @foo="bar = $event"></Foo>
<p>{{bar}}</p>
</div>
<script src="index.js"></script>
</body>
</html>
index.js
Vue.component("Foo", {
methods: {
emit() {
this.$emit("foo", "bar");
}
},
template: `<button @click='emit'>Emit</button>`
});
new Vue({
el: "#app",
data: {
bar: ""
}
});
In the code above, we defined a Foo
component with an emit
method that emits an event called foo
with the payload 'bar'
.
Then in our template, we attached a listener to the template where we referenced our Foo
component.
This is where we have:
<Foo @foo="bar = $event"></Foo>
We display assigned item in:
<p>{{bar}}</p>
Then when we click Emit, the foo
event is emitted with the value 'bar'
.
'bar'
is assigned to $event
. Then it’s set to bar
in the parent component and displayed.
Whatever name we set it to, it’ll be the event name that’s used to attach event listeners. There’s no transformation of the names.
Customizing Component v-model
v-model
is shorthand for @input
and :value
together. We can change that since Vue 2.2.0 to make v-model
listen to other event names and bind to different props.
We can add the model
property to our component so that v-model
can listen to the event name and pass in props with names that we specify.
For example, we can write:
Vue.component("Foo", {
model: {
prop: "checked",
event: "change"
},
data() {
return {
checked: false
};
},
template: `
<div>
<label>foo</label>
<input
type="checkbox"
:checked="checked"
@change="$emit('change', $event.target.checked)"
>
</div>
`
});
new Vue({
el: "#app",
data: {
bar: false
}
});
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Foo v-model="bar"></Foo>
<p>{{bar}}</p>
</div>
<script src="index.js"></script>
</body>
</html>
In the code above, we have:
model: {
prop: "checked",
event: "change"
}
to specify that the parent’s v-model
directive in the parent listens to the change
event and pass data for the checkbox into the checked
prop.
Now we should see the value of the checkbox displayed in the p tag below the Foo
component as we click the checkbox.
Conclusion
We can emit custom events with Vue with the $emit
method. It takes the name of the event as the first argument, and the value we want to emit in the second argument.
Then we can listen to the event and get the payload in the parent component.
We can customize v-model
by setting the prop that v-model
passes the value to and then event it listens to from the child component to set the value of the specified model.