Reputation: 8218
I am fairly new to vue and trying to figure out the best way to structure my event bus. I have a main layout view (Main.vue
) inside of which I have a router view that I am passing a child's emitted info to like so:
<template>
<layout>
<router-view :updatedlist="mainupdate" />
</layout>
</template>
import { EventBus } from './event-bus.js'
export default {
data () {
return {
mainupdate: []
}
},
mounted () {
EventBus.$on('listupdated', item => {
this.mainupdate = item
console.log(item)
})
}
}
The structure looks like: Main.vue
contains Hello.vue
which calls axios
data that it feeds to child components Barchart.vue
, Piechart.vue
, and Datatable.vue
The axios call in Hello.vue
populates a data property called list
. I then check if updatedlist
(passed as router prop from Datatable.vue
to Main.vue
when something changes) is empty, and if so set it to the value of list
I know that the event is being emitted and received by Main.vue
because the console.log(item)
shows the data. But my child components are not getting updated, even though they are using updatedlist
as their data source. (If I reload the page, they will be updated btw, but why aren't they reactive?)
UPDATE: I thought I would cut out the top level parent Main.vue
and just put my EventBus$on inside Hello.vue
instead and then just change list
when it was received. But this does two things, neither of which are great:
UPDATE 2: UGH. I think I see why they aren't updating, the problem is with the reactivity in my chartsjs component, so I will have to resolve that there (Barchart.vue
, Piechart.vue
). A simple component I built myself to just read the total length DOES get updated, so that works. This still leaves the mystery of the massive number of duplicate console logs though, any ideas?
Upvotes: 0
Views: 4317
Reputation: 82459
It sounds like you may have the answer to the original question? To answer your last update you likely have duplicate logs because you do not appear to be removing event handlers. When you add an event handler to a bus like this:
mounted () {
EventBus.$on('listupdated', item => {
this.mainupdate = item
console.log(item)
})
}
}
You need to remove it yourself. Otherwise you are just adding a new handler every time the component is mounted.
I suggest you move the actual handler into a method:
methods: {
onListUpdated(item){
this.mainupdate = item
console.log(item)
}
}
Move code to add the handler to created:
created() {
EventBus.$on('listupdated', this.onListUpdate)
}
}
And add a beforeDestroy handler:
beforeDestroy(){
EventBus.$off("listupdated", this.onListUpdate)
}
And do that in every component that you are adding event handlers to EventBus
.
Upvotes: 3
Reputation: 6802
I' not aware if you require to stick to the current structure. For me the following works perfectly fine.
// whereever you bootstrap your vue.js
// e.g.
window.Vue = require('vue');
// add a central event bus
Vue.prototype.$bus = new Vue();
Now you can simply access the event bus in every component by using
this.$bus.$on( ... )
As said I'm not aware of your full event bus code but this should actually work fine
Upvotes: 0