When <router-view/> changed,why can the old component of router still '$on' and handle the event?

Viewed 88

emmmmm...let me explain the situation I meet. I have a parent component with two children that both litsen the same event and do the same thing.(codes below):

mounted() {
 EventBus.$on('edit', (data) => {
  console.log('service called')
  this.showRightSide(data)
 })
},

showRightSide(data) {
  console.log(data)
  // display right-side operator edit page.
  this.$store.commit({
    type: 'setShownState',
    shown: true
  })
  // giving operator name & operator type
  this.$store.commit({
    type: 'setOptName',
    optName: data.name
  })
  this.$store.commit({
    type: 'setOptType',
    optType: data.type
  })
},

with the vue router below

{
  path: '/main',
  name: 'Main',
  component: Main,
  children: [
    { path: 'service', name: 'Service', component: ServiceContent },
    { path: 'model', name: 'Model', component: ModelContent }
  ]
},

There should be three commits during each 'edit' event, isn't it?

In fact. Firstly it has 3 commits.

But when I change from '/main/service' to '/main/model', it made 6 commits during each 'edit' event(the old ServiceContent component still made 3 commits and the new ModelContent component offers 3 commits).

when I back to '/main/service', 9 commits!!!

devtool:

enter image description here

It seems that when router-view changed, the component of old view can still listen the event, how can I fix it? (EventBus is just a global vue instance used as a bus)

2 Answers

When you call $on(), Vue registers your callback function internally as an observer. This means your function lives on, even after the component is unmounted.

What you should do is use $off when your component is unmounted.

For example

methods: {
  showRights (data) {
    // etc
  }
},
mounted () {
  EventBus.$on('edit', this.showRights)
},
beforeDestroy () {
  EventBus.$off('edit', this.showRights)
}

I would start with manually cleaning up listeners in your beforeUnmount function. Because of the way that JS works with garbage collection, I would be surprised if vue is smart enough to clean up externally reference stuff like this.

methods: {
  handleEventBusEdit(data) {
    console.log('service called')
    this.showRightSide(data)
  }
},
mounted() {
 EventBus.$on('edit', this.handleEventBusEdit)
},
beforeDestroy() {
  EventBus.$off('edit', this.handleEventBusEdit)
}
Related