You might have realized that $emit
is scoped to the component that is emitting the event. That's a problem when you want to communicate between components far from one another in the component tree.
Note: In Vue1 you coud use $dispatch
or $broadcast
, but not in Vue2. The reason being that it doesn't scale well.
There is a popular bus
pattern to manage this:
HTML
<script type="x-template" id="sender">
<button @click="bus.$emit('new-event')">Click me to send an event !</button>
</script>
<script type="x-template" id="receiver">
<div>I received {{numberOfEvents}} event{{numberOfEvents == 1 ? '' : 's'}}</div>
</script>
<sender></sender>
<receiver></receiver>
JS
var bus = new Vue();
var senderComponent = {
template: '#sender',
data() {
return {
bus: bus
}
}
};
var receiverComponent = {
template: '#receiver',
data() {
return {
numberOfEvents: 0
}
},
ready() {
var self = this;
bus.$on('new-event', function() {
++self.numberOfEvents;
});
}
};
new Vue({
el: 'body',
components: {
'sender': senderComponent,
'receiver': receiverComponent
}
});
You just need to understand that any Vue()
instance can $emit
and catch ($on
) an event. We just declare a global Vue
instance call bus
and then any component with this variable can emit and catch events from it. Just make sure the component has access to the bus
variable.