Make your vuex store globally available by registering it as a plugin

Vuex is awesome. But, if you're like me, you find yourself importing it in your application almost everywhere. So .. why not just make it globally available?

By the end of this tutorial, you will have a vuex store that can be accessed anywhere in your app via:

this.$myStore  

yay :).

Setting up

First things first, let's set up a simple project with a vuex store. We'll be using the Vue CLI and webpack starter template.

(If you know how vuex works, you can skip this section and go down to: Vuex as a plugin).

Create a new vue project

vue init webpack globalvuex  

Answer the questions and follow the instructions. All-righty, project setup. Now let's add vuex

Setup vuex

Install vuex

npm install --save vuex  

Create a basic store

Note: this article assumes you have a basic understanding of how Vuex works. If Vuex is new to you, I'd recommend you read through the Vuex getting started docs before continuing

In the same directory as main.js, create a file called store.js and paste this into it:

store.js:

import Vue from 'vue'  
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({  
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

To setup our app to use Vuex, we simply import it and .use() it. To main.js add:

...
import Vuex from 'vuex'  
Vue.use(Vuex)  
...

So now, main.js should look something like this:

main.js

import Vue from 'vue'  
import App from './App'  
import router from './router'

import Vuex from 'vuex'  
Vue.use(Vuex)

/* eslint-disable no-new */
new Vue({  
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

Finally, let's make sure it's all working. Edit src/components/Hello.vue to be:

src/components/Hello.vue:

<template>  
  <div class="hello">
    <h1>The count is: {{ count }}</h1>
  </div>
</template>

<script>  
import store from '../store'  
export default {  
  store,
  name: 'hello',
  data () {
    return {
      count: store.state.count
    }
  }
}
</script>  

Notes:

  • We import our Vuex store: import store from '../store',
  • We inject the store into our Vue component: export default { store, ...
  • We set the data value from the store: count: store.state.count

You can now run the app, and you should see something like this in your browser:

App output

So, now vuex is all setup. Now let's expose it as a plugin.

Vuex as a plugin

In the same directory as main.js, create a file storePlugin.js:

storePlugin.js

import store from './store'  
export default {  
  store,
  install (Vue, options) {
    Vue.prototype.$myStore = store
  }
}

This is as simple as plugins get. Essentially, install() is a hook that we can use to add properties directly to the Vue prototype. These properties are now available on the global Vue instance (that's this when you're in the context of a component). For more information on Vue plugins, this is quite a good article.

So all we're doing here is setting $myStore to be our Vuex store. Vue really does make things easy for us!

The last thing we need to do is tell our main Vue instance to use our plugin. In main.js, we import our plugin and tell Vue to use it:

main.js

import storePlugin from './storePlugin'  
Vue.use(storePlugin)  

So now my main.js file looks like this:

import Vue from 'vue'  
import App from './App'  
import router from './router'

import Vuex from 'vuex'  
Vue.use(Vuex)

import storePlugin from './storePlugin'  
Vue.use(storePlugin)

/* eslint-disable no-new */
new Vue({  
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

And just like that, we can now use the store directly in our components with this.$myStore .. just like magic.

So let's do that. In src/components/Hello.vue, let's remove the explicit import of our store and use the plugin version:

src/components/Hello.vue:

export default {  
  name: 'hello',
  data () {
    return {
      count: this.$myStore.state.count
    }
  }
}

And that's it .. you should see the same output as above \o/.

Just for fun, let's add the increment part. In src/component/Hello.vue:

Add an increment method:

...
  methods: {
    doIncrement () {
      this.$myStore.commit('increment')
    }
  }
...

Move count to be a computed value rather than data so that it's reactive

...
  computed: {
    count () {
      return this.$myStore.state.count
    }
  },
...

So now the script for: src/components/Hello.vue should look something like this:

export default {  
  name: 'hello',
  computed: {
    count () {
      return this.$myStore.state.count
    }
  },
  methods: {
    doIncrement () {
      this.$myStore.commit('increment')
    }
  }
}

An we now have an awesome counter app:

Awesome counter app

Todo: distribute this basic setup as a VueCLI web template

You can get the code for this tutorial at: https://github.com/toast38coza/global-vuex-plugin

References: