How should I handle events in Vuex?
Asked Answered
P

3

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?

Pricillaprick answered 15/3, 2017 at 23:57 Comment(0)
U
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.

Umber answered 16/3, 2017 at 2:19 Comment(4)
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!Pricillaprick
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.Umber
@Blue_Dragon360 I was struggling with the same problem, then I came across this post which essentially says the same thing as Saurabh. forum.vuejs.org/t/bus-vs-vuex/6679Stonebroke
See this example how they are using bothLoot
C
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')
Closestool answered 12/10, 2020 at 5:20 Comment(1)
Commenting 4 years later... It could be problematic when the user opens multiple tabs and the action is intended for the current view.Gump
M
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

Macruran answered 22/5, 2021 at 7:51 Comment(1)
thx a lot for this very instructive exampleSharkey

© 2022 - 2024 — McMap. All rights reserved.