Reputation: 2801
I've seen this question and tried both the this.$parent
and the this.$root
alternatives, to no avail. The situation is as follows.
App.vue
<template>
<div id="app">
<global-notifications/>
<router-view></router-view>
</div>
</template>
<script>
import GlobalNotifications from "./components/GlobalNotifications.vue"
export default {
name: "app",
components: {
GlobalNotifications
}
};
</script>
GlobalNotifications.vue
<template>
<div>
<p>Notifications:</p>
<p v-for="n in notifications" :key="n.id">{{ n }}</p>
<b-button @click="internalEmitter">Internal notification!</b-button>
</div>
</template>
<script>
export default {
data() {
return {
notifications: []
}
},
methods: {
appendNotification(n) {
this.notifications = [...this.notifications, n]
},
internalEmitter() {
let message = { id: `${Math.floor(Math.random()*1000000)}`, message: 'From the inside!' }
this.$emit('global-notification', message)
}
},
mounted() {
this.$on('global-notification', this.appendNotification)
},
beforeDestroy() {
this.$off('global-notification', this.appendNotification)
}
}
</script>
Dashboard.vue
Gets loaded through the router. Yes, I tried loading it directly from App.vue
.
<template>
<b-button @click="emitTheThing">External notification!</b-button>
</template>
<script>
export default {
methods: {
emitTheThing() {
let message = { id: `${Math.floor(Math.random()*1000000)}`, message: 'From the outside!' }
this.$emit('global-notification', message)
}
}
}
</script>
When I click on the Internal notification!
button, I get events fired and caught, and everything works as expected. However, when I click on the External notification!
button, the only evidence of events flying around that I can see is in the Vue Dev Tools, where I see events being emitted.
As I said, I tried emitting on $parent
and even on $root
, but I only see the events in the dev tools, being emitted on <App>
and <Root>
, respectively. However, the GlobalNotification
child does not seem to catch them.
What am I missing?
Upvotes: 1
Views: 2403
Reputation: 138696
The problem is the <global-notifications>
component listens for events on itself, while you're emitting the event on the root component. Note that emitting the event on a root component does not broadcast the event to the root's child components (as you've observed with Vue DevTools).
A quick fix in your case is to use $root.$on()
so that it sets up the listener on the root component:
mounted() {
// this.$on('global-notification', this.appendNotification)
this.$root.$on('global-notification', this.appendNotification)
},
Then, you can use $root.$emit()
from any component in any heirarchy to emit an event to the root component.
Upvotes: 3