Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js event emitting from child component to (grand)parent component using global eventbus

I want to use a global eventbus to emit events from a child up to a (grand)parent.

In My main.js: I make a global eventbus available to all components.

import Vue from 'vue'
import App from './App'
const eventHub = new Vue()

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

Vue.mixin({
  data: function () {
    return {
      eventHub: eventHub
    }
  }
})

Then, in my Childcomponent.vue: I emit an event to the eventbus on a click event

<template>
  <button @click="save">Save</button>
</template>

<script>
  let data = {
    columnName: '',
    order: 0
  }

  export default {
    ...
    name: 'init-column',
    methods: {
      save: function () {
        this.eventHub.$emit('newColumn', data)
      }
    }
    ...
  }
</script>

Then, in a Parentcomponent.vue I want to catch this event and do something with the data that the child had transmitted:

<template>
  <div id="app">
      <column v-for="column in allData"></column>
      <init-column v-if="newColumn"></init-column>
    </div>
  </div>
</template>

<script>
  import initColumn from './components/Init-column'

  let newColumn = false

  export default {
    ...
    name: 'project',
    ready: function () {
      this.eventHub.$on('newColumn', (event) => {
        console.log(event)
      })
    }
    ...
  }
</script>

I'm not sure where to put the $on listener, I saw examples where they put $on in the ready hook. The code above does nothing, however I get no error in the console.

like image 794
marchello Avatar asked Dec 04 '22 23:12

marchello


1 Answers

The ability to do this goes away with Vue 3. The RFC below mentions the motivation and links to some issues for further help.

https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md


I don't think data is the right place for the event bus. I definitely wouldn't use a global mixin for it either.

What I've done in the past is have a simple bus.js file like:

import Vue from 'vue'
export default new Vue()

Then, in any component that needs the bus I just

import bus from './bus.js'

Then I normally do this to emit events.

bus.$emit('foo', whatever)

and this to catch them

created () {
  bus.$on('foo', this.someMethod)
}

I prefer to do it in created since that's the earliest step in the lifecycle you can do this.

Also, this issue on github has some very nice examples: https://github.com/vuejs/vuejs.org/pull/435

like image 139
Bill Criswell Avatar answered Dec 11 '22 16:12

Bill Criswell