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:
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:
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:
- https://alligator.io/vuejs/creating-custom-plugins/
- https://vuejs.org/v2/guide/plugins.html
- https://vuex.vuejs.org/