Communicating between Vue components with Vuex

In this tutorial, you will learn how you can make vue.js components communicate to each other using Vuex. Making components communicate in Vue can be done in multiple ways. In this tutorial, you will build two components that communicate through a shared state in a structured manner, using Vuex.

Introduction

Vuex is state management for Vue. We try it out as an indirect means of communication between components. There are no particular skills you should have to carry out this article, but you should have at least an understanding of what the Flux pattern is, since Vuex is is inspired by Flux, Redux, and The Elm Architecture. You can find more information at https://facebook.github.io/flux/docs/overview.html.

Let’s Get Start

We will centralize the state of our whole application in a Vuex store. To install Vuex, you can add it as a dependency (more instructions at https://vuex.vuejs.org/en/installation.html); for now, I will assume that you are working on JSFiddle or a single web page, in which you can add https://unpkg.com/vuex as a dependency.

We declare a new store for our state:

const store = new Vuex.Store({})

We then add properties to the empty object inside the parenthesis, just like we would do with a Vue instance.

First, we will tell Vuex to help us debug by noticing us every time we modify the state outside of a mutation:

strict: true

Then, we will declare the state that we will use to characterize the whole system:

state: { 
  currentActor: -1, 
  currentLine: -1, 
  actors: [], 
  dialogue: [ 
    'Where are you going?', 
    'To the cinema', 
    'What's on at the cinema?', 
    ''Quo vadis?'', 
    'Oh, what does it mean?' 
  ] 
}

We will fill in the actor array with objects that will represent the actors themselves. Moreover, we will access the actor and dialogue arrays in a circular manner.

The next things you have to write inside the Vuex store object are the mutations. Define one mutation that will add one actor to the scene and one mutation that will advance the current line by one:

mutations: { 
  entersScene (state, uuid) { 
    state.currentLine =  
      (state.currentLine + 1) % state.dialogue.length 
    state.actors.push({ 
      uuid, 
      line: state.dialogue[state.currentLine] 
    }) 
    state.currentActor =  
      (state.currentActor + 1) % state.actors.length 
  }, 
  nextLine (state) { 
    state.currentActor =  
      (state.currentActor + 1) % state.actors.length 
    state.currentLine =  
      (state.currentLine + 1) % state.dialogue.length 
    state.actors[state.currentActor].line =  
      state.dialogue[state.currentLine] 
  } 
}

You successfully completed the store. Now you need to define the component.

Vue.component('blabber', { 
  template: '<div class="blabber">{{currentLine}}</div>', 
  data () { 
    return { 
      uuid: Math.random() 
    } 
  }, 
  computed: { 
    currentLine () { 
      return store.state.actors.find(actor => 
        actor.uuid === this.uuid).line 
    } 
  }, 
  created () { 
    store.commit('entersScene', this.uuid) 
  } 
})

The blabber component has a simple template (it just says its line). It retrieves its line from the store with a computed property and, at creation time, signals its entrance to the store.

You can put two blabbers in the HTML:

<div id="app"> 
  <blabber></blabber> 
  <blabber></blabber> 
</div>

Maybe add some style to frame your blabbers with some border through CSS:

.blabber { 
  width: 200px; 
  height: 40px; 
  background-color: gainsboro; 
  border: 1px solid grey; 
}

The last thing you have to do to make all this machinery work is to commit the nextLine mutation to the store every 2 seconds so that the show goes on. You can do it in the Vue instance by installing a setInterval:

new Vue({ 
  el: '#app', 
  mounted () { 
    setInterval(() => { 
      store.commit('nextLine') 
    }, 2000) 
  } 
})

When you launch the application now, you will see the two blabbers talking in circle for hours.

How it works?

The blabbers always know their line because they communicate indirectly through the store.

If you look closely, the blabbers themselves have no state. Yeah they have a UUID (Universally Unique Identifier), but that is just to give them an identity, and it never really changes.

Their state is centralized in the store, and the actor array will look like this during execution:

[{ 
  uuid:0.9465735043368413, 
  line:"'Quo vadis?'" 
}, 
{ 
  uuid:0.8398547513423675, 
  line:"Oh, what does it mean?" 
}]

Thanks to Vue reactivity, the component is just a mirror of this state.

The communication, while indirectly, is done in the store. Every 2 seconds, a nextLine mutation is issued:

nextLine (state) { 
    state.currentActor =  
      (state.currentActor + 1) % state.actors.length 
    state.currentLine =  
      (state.currentLine + 1) % state.dialogue.length 
    state.actors[state.currentActor].line =  
      state.dialogue[state.currentLine] 
  }

This advances the currentActor and the currentLine  indexes by one step; after that, the actor at the currentActor index says the line at the currentLine index. The actors don’t communicate directly to each other, instead they just watch the result (line) of a shared counter (the currentLine) that advances at every step.

Muhammad Mubeen

Muhammad Mubeen

Mubeen is a full-stack web & mobile app developer who is very proficient in MEAN.js, Vue, Python, Ionic 4, Flutter, Firebase, ROR, and PHP. He has created multiple mobile and web applications. He is very passionate about sharing his knowledge.

Leave a Reply

Your email address will not be published. Required fields are marked *

Trending