-
Notifications
You must be signed in to change notification settings - Fork 232
Vuex
In this section of the tutorial we'll look at central state management with Vuex...
Let's setup the state of our central data storage. We'll want some state to be available across browser tabs (and when the app is closed/reopened) so let's sync this state with LocalStorage. When the app bootstraps, we want to first check in the browser's localStorage and retrieve all of our previously stored data. We'll also have other state we can use for to make component-to-component communication easier (for situations where you don't have a simple parent-child communication, but more complex sibling-to-sibling or other component relationships). Let's just add a property for storing the search text and button press on the navbar for demonstration purposes.
$ npm install vuex --save-dev
Vuex-router-sync will help us get the current routing information from the store:
$ npm install vuex-router-sync
src/vuex/state.js
/**
* Key for local storage.
*
* Set the key to use in local storage to hold persistant data. If logged in,
* you can see this key by going to Chrome > dev tools > application tab,
* then choosing "Local Storage" and "http://localhost:8080".
*
* @type {string}
*/
export const STORAGE_KEY = 'vue-example-project'
/**
* Initialize all the shared app state in Vuex.
*
* @return {Object}
*/
function initializeState () {
let syncedState = {
auth: {
isLoggedIn: false,
accessToken: null,
refreshToken: null
},
user: {
name: null
}
}
const notSyncedState = {
sidebar: false,
currentView: null
}
// Sync with local storage.
if (localStorage.getItem(STORAGE_KEY)) {
syncedState = JSON.parse(localStorage.getItem(STORAGE_KEY))
}
return Object.assign(syncedState, notSyncedState)
}
/**
* The shared app state in Vuex.
*
* @type {Object}
*/
export const state = initializeState()
Now create a file to hold all the methods that will change the state in our Vuex store:
src/vuex/mutations.js
/**
* Update auth data in Vuex.
*
* @param {state} state The full existing data we have stored in Vuex.
* @param {auth} auth The new auth data.
* @return {void}
*/
export const UPDATE_AUTH = (state, auth) => {
state.auth = auth
}
/**
* Update user data in Vuex.
*
* @param {state} state The full existing data we have stored in Vuex.
* @param {user} user The new user data.
* @return {void}
*/
export const UPDATE_USER = (state, user) => {
state.user = user
}
/**
* Open/Close the app sidebar.
*
* @param {state} state The full existing data we have stored in Vuex.
* @param {Boolean} open The open/close status.
* @return {void}
*/
export const UPDATE_SIDEBAR = (state, open) => {
state.sidebar = open
}
/**
* Update the current view (used to navigate back/forth to child pages).
*
* @param {state} state The full existing data we have stored in Vuex.
* @param {Boolean} open The open/close status.
* @return {void}
*/
export const UPDATE_CURRENT_VIEW = (state, view) => {
state.currentView = view
}
/**
* Clear each property, one by one, so reactivity still works.
*
* @param {state} state The full existing data we have stored in Vuex.
* @return {void}
*/
export const CLEAR_ALL_DATA = (state) => {
// Auth
state.auth.isLoggedIn = false
state.auth.accessToken = null
state.auth.refreshToken = null
// User
state.user.name = ''
}
And some getters (although you can accesss the Vuex state directly as we'll see shortly):
src/vuex/getters.js
export const user = state => state.user
And some getters (although you can accesss the Vuex state directly as we'll see shortly):
src/vuex/plugins.js
import { STORAGE_KEY } from './state'
/**
* @param {Vuex}
* @return {Function}
*/
const localStoragePlugin = store => {
store.subscribe((mutation, state) => {
const syncedData = { auth: state.auth, user: state.user }
localStorage.setItem(STORAGE_KEY, JSON.stringify(syncedData))
if (mutation.type === 'CLEAR_ALL_DATA') {
localStorage.removeItem(STORAGE_KEY)
}
})
}
/**
* Export an array of all the plugins.
*
* @type {array}
*/
export default [localStoragePlugin]
And bring it all together in the index.js file:
_src/vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { state } from './state'
import * as getters from './getters'
import * as actions from './actions'
import * as mutations from './mutations'
import plugins from './plugins'
Vue.use(Vuex)
/**
* All the parts we need to implement shared state across our app with Vuex.
*
* @type {Vuex}
*/
const store = new Vuex.Store({
state,
getters,
actions,
mutations,
plugins
})
/**
* Export the store object.
*
* @type {Vuex}
*/
export default store