37

I am used to using a global event bus to handle cross-component methods. For example:

var bus = new Vue();
...
//Component A
bus.$emit('DoSomethingInComponentB');
...
//Component B
bus.$on('DoSomethingInComponentB', function(){ this.doSomething() })

However, I am building a larger project, which requires global state management. Naturally, I want to use Vuex.

While this bus pattern works with Vuex, it seems wrong. I have seen Vuex recommended as a replacement for this pattern.

Is there a way to run methods in components from Vuex? How should I approach this?

Aaa
  • 900
  • 3
  • 9
  • 22

3 Answers3

38

Vuex and event bus are two different things in the sense that vuex manages central state of your application while event bus is used to communicate between different components of your app.

You can execute vuex mutation or actions from a component and also raise events from vuex's actions.

As the docs says:

Actions are similar to mutations, the difference being that:

  • Instead of mutating the state, actions commit mutations.
  • Actions can contain arbitrary asynchronous operations.

So you can raise an event via bus from actions and you can call an action from any component method.

tony19
  • 125,647
  • 18
  • 229
  • 307
Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • 8
    So using the bus and vuex at the same time is an OK pattern? Seems to contradict what's said in the docs, but I'll roll with it for now :) Thanks! – Aaa Mar 16 '17 at 05:34
  • 5
    Yes, in my opinion, you can use both together depending on the use-case. Once can replace all the functionality of event Bus by Vuex, but for a simple use case(communication between two components, trigger method of another component, etc) you can use event bus, while for place where you need one variable by multiple components and all modifying it, you can use vuex. – Saurabh Mar 16 '17 at 05:39
  • 6
    @Blue_Dragon360 I was struggling with the same problem, then I came across this post which essentially says the same thing as Saurabh. https://forum.vuejs.org/t/bus-vs-vuex/6679 – Amrit Kahlon Sep 28 '17 at 22:06
  • 3
    See [this](https://github.com/DivanteLtd/vue-storefront) example how they are using both – Henry H. Aug 01 '18 at 21:16
1

Using a global event bus is an anti pattern because it becomes very difficult to trace it (where was this event fired from? Where else are we listening to it? etc.)

Why do you want to use a global event bus? Is there some method that you want to trigger in another component? If you use Vuex then all your actions (methods) are in one central state and you can just dispatch your action.

So for example instead of doing this..

// Component A
bus.$emit('DoSomethingInComponentB');

// Component B
bus.$on('DoSomethingInComponentB', function(){ this.doSomething() })

With Vuex you would have the doSomething() function in a central store as an action. Then just make sure to convert you local component data to a global Vuex state data and dispatch that action.

this.$store.dispatch('doSomething')
Martin Zeltin
  • 2,496
  • 3
  • 18
  • 36
0

It may not be directly what you are looking for, but I use watchers to respond to state changes. I come from an Angular background where having side effects respond to actions makes sense to me. To make this work I am having a particular value in the store change and then watch for the value in the relevant component like so:

Vue.component('comp-2', {
  ...
  watch: {
    mod1Foo() {
      // do something here when the store value of the getter
      // mod1/getFoo changes
    }
  },
  computed: {
    ...mapGetters({
      mod1Foo: 'mod1/getFoo'
    })
  }
});

Here is a full StackBlitz example: https://stackblitz.com/edit/js-gdme1g

Ian Jamieson
  • 4,376
  • 2
  • 35
  • 55