State management is something you will ultimately have to deal with as you create increasingly complex frontend applications. Thankfully, with the help of Vuex, this isn’t as hard as you may think!
Installation
In order to install vuex
, you will have to use either yarn
or npm
like so:
# Npm
$ npm install vuex
# Yarn
$ yarn add vuex
Setting up Vuex
Once you have successfully installed Vuex in your VueJS application, you can set your application to use it by doing the following within your main.js
file:
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App'
import router from './router'
// Import the store from the file we are about to create
import { store } from './store/index.js'
Vue.config.productionTip = false
Vue.use(Vuex)
/* eslint-disable no-new */
new Vue({
el: '#app',
// tell our vue instance to use our store
store: store,
router,
components: { App },
template: '<App/>'
})
We then have to define our /src/store/index.js
file which will contain our Vuex.Router()
object which we’ve imported and used in our main.js
file above.
Core Concepts
So, there are 5 core concepts you will have to become familiar with if you wish to use vuex
as your application’s state management system.
State
State is the object representation of your applications state. This could be as simple as this if we wanted to store a ‘name’ value within our application:
import Vuex from 'vuex'
import Vue from 'vue'
export const store = new Vuex.Store({
state: {
name: 'elliot'
}
})
If we wanted to make it more complex then we simply need to expand out our state object to store everything we need. This could be arrays, boolean values, nested objects or any of the 5 primitives types within JavaScript.
Mutations
Mutations within the vuex
world allow us to update the state
of our application. These are very similar to event handlers and each mutation has a string type and a handler.
Effectively, if you wished to update the name
within our state
object above, you could do so through a mutation
. This mutation
has to be invoked through the use of an action
which we’ll cover in the next section.
Let’s have a look at how we would create a updateName
mutation which would allow us to change our name
value within our state
object:
import Vuex from 'vuex'
import Vue from 'vue'
export const store = new Vuex.Store({
state: {
name: 'elliot'
},
mutations: {
updateName (state, newname) {
state.name = newname
}
}
})
Actions
Actions allow us to commit
mutations. What this means is that should we wish to update the name
of our state
object above, we would trigger an action using the store.dispatch()
method and passing in the string name of the action we wish to call.
The main reason we have this level of abstraction away from our mutations
is so that we can make asynchronous requests. All mutations have to be synchronous, so by having our actions
perform any asynchronous code and then commit
-ing the result to a mutation, we manage to get round this.
import Vuex from 'vuex'
import Vue from 'vue'
export const store = new Vuex.Store({
state: {
name: 'elliot'
},
mutations: {
updateName (state, newname) {
state.name = newname
}
},
actions: {
updateName ({ commit }) {
commit('updateName', 'Sophie')
}
}
})
Whenever we trigger the updateName
action, the name
stored within our state
object will subsequently be updated to Sophie
.
We can trigger an action
by doing the following:
store.dispatch('updateName')
Due to the way we have registered our vuex
store within our application, you can typically trigger this like so:
this.$store.dispatch('updateName')
Getters
There are some situations where we need to get compute a derived state based on stored state. For example, say we wanted the first initial of our name
value that we have already stored, we could define a Getter
that would compute this for us, cache the result and then return the result.
This caching is a major benefit and can help us to improve the performance of our application. Getters
also refresh the cached result should any of the data that our result dependes upon be changed.
For example, if we had a name
set to elliot
originally, and we had a getter
that returned e
as the first initial, this e
result would be cached for us. However, when we update the name by dispatching an action
, this result would be updated to S
as that would be the initial of Sophie
.
import Vuex from 'vuex'
import Vue from 'vue'
export const store = new Vuex.Store({
state: {
name: 'elliot'
},
mutations: {
updateName (state, newname) {
state.name = newname
}
},
actions: {
updateName ({ commit }) {
commit('updateName', 'Sophie')
}
},
getters: {
firstInitial: state => {
return state.name[0]
}
}
})
If you are doing more expensive operations such as filtering a large list of objects then this starts to become more beneficial.
Modules
Still under construction
Conclusion
Hopefully, you found this tutorial on vuex
useful and it showed you everything you need in order to get started using it within your own Vue.js applications.