3đź‘Ť
Other than the small typo in your $on
, it’s not clear what you’re doing wrong, as you haven’t provided enough context, but here’s a working example of exactly what you’re trying to do (send and receive an event via the $root
element, without instantiating a separate eventbus Vue instance). (Many people do prefer to do the message passing via a separate instance, but it’s functionally similar to do it on $root
.)
I included a payload object to demonstrate passing information along with the event.
Vue.component('sender', {
template: '<span><button @click="send">Sender</button></span>',
methods: {
send() {
console.log("Sending...")
this.$root.$emit('eventName', {
message: "This is a message object sent with the event"
})
}
}
})
Vue.component('receiver', {
template: '<span>Receiver component {{message}}</span>',
data() {return {message: ''}},
mounted() {
this.$root.$on('eventName', (payload) => {
console.log("Received message", payload)
this.message = payload.message
})
}
})
new Vue({
el: '#app'
});
<script src="https://unpkg.com/vue@latest/dist/vue.min.js"></script>
<div id="app">
<sender></sender>
<receiver></receiver>
</div>
Personally I don’t tend to use this pattern much; I find it’s better to handle cross-component communication from parent to child as props, and from child to parent as direct $emit
s (not on $root
). When I find I’m needing sibling-to-sibling communication that’s generally a sign that I’ve made some poor architecture choices, or that my app has grown large enough that I should switch over to vuex. Piling all the event messaging into a single location, whether that’s $root
or an eventbus instance, tends to make the app harder to reason about and debug.
At the very least you should be very explicit in naming your events, so it’s easier to tell where they’re coming from; event names such as “handleClick” or just “event” quickly become mysterious unknowns.
2đź‘Ť
So what you are looking for is an event bus (global events)
I’d advise considering using vuex anytime you have the need to implement an event bus.
Let’s get back to the problem.
Create a file event-bus.js
this is what’s going to be capturing and distributing events.
import Vue from 'vue'
const EventBus = new Vue()
export default EventBus
Now in your main.js
register your event bus
import Vue from 'vue'
import eventBus from './event-bus'
//other imports
Vue.prototype.$eventBus = eventBus
new Vue({
...
}).$mount('#app')
Now you can:
- listen for events with
this.$eventBus.$on(eventName)
- emit events
this.$eventBus.$emit(eventName)
0đź‘Ť
If component 2 is the parent of the component 1 you could do:
getMyProfile(){
this.$emit('myevent');
console.log("emited")
},
for componant 2 componant like
<componant-2 @myevent="dosomething" ...></componant-2>
and in componant two
methods: {
dosomething() {
console.log('Event Received');
}
}
0đź‘Ť
in this example i’ll bring event from child to parent component with $emit
Child Component:
Vue.component('Child component ', {
methods: {
getMyProfile: function() {
this.$emit('me-event', 'YUP!')
}
},
template: `
<button v-on:click="getMyProfile">
Emmit Event to Parrent
</button>
`
})
Parent Component:
Vue.component('Parent component ', {
methods: {
getEventFromChild: function(event) {
alert(event)
}
}
template: `
<div>
<Child-component v-on:me-event="getEventFromChild" />
</div>
`
})
for example when you have data flow one way from parent to child and you want to bring data from child to parent you can use $emit and bring it from child.. and in the parent you must catch it with v-on directive. (sry form my english)