Introduction to Vuex

This a short introduction to Vuex a State Management tool for Vue.js. To understand all it's complexities I would recommend you to read the documentations, this article is intended as an introduction only.

What is the use of Vuex

Let me first quote the official documentation, for it describe Vuex precisely, although a bit technically:

Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

What Vuex is in other words are is a central unit of your application to store the global state of your variables. This can for example be the current logged in user, you could save that to $store.state.user in that way whenever a component needs to access, let's say the user id, it can be done through this.$store.state.user.id.

The Vuex can also have getters, so you could take advantage of this, and have a getter for retrieving the user object. If the user hasn't currently been loaded it could take responsibility for loading it the first time, and after that return the value in the store.

It could also be used to tell if the application is online or offline, if you make a PWA (Progressive Web Application).

How it's structured and implemented

To use Vuex you must first create a store. This I usually do by creating a store.js file with the content:

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

Vue.use(Vuex)

export const store = new Vuex.Store({
    state: {},
    mutations: {},
    actions: {},
    getters: {}
})

In your index.js, app.js or what other name it might have, where you initialise Vue, you must tell it to also load your Vuex Store:

// Include Vuex Store
import { store } from './store'

const app = new Vue({
    el: '#app',
    store // Load Vuex as `store`
});

Now you can access the store from any component by referring to $store:

this.$store.state.myState

I would suggest to take a look at Core Concepts in order to get a better understanding of the different parts: https://vuex.vuejs.org/

Vuex namespacing and modules

As with most things it's a lot easier to maintain if you keep things organised. To help you with this Vuex has feature for modules and namespaces.

To install a module from a file unrelated to the store.js use the Vue.use({}) mechanism to install your additional features.

I have created a small implementation I call bind, although it don't use namespaces – and this would increase the complexity anyway – it demonstrates how to build modules. This module is intended to serve as an easy access to a state. I also included the mixin that gives some nice handy features:

Vue.mixin({
    methods: {
        /**
         * Connect every component to the bind operator.
         *
         * @param  {string} property Node to bind to
         * @param  {mixed}  value    Value to assign
         * @return {mixed}           Value that was assigned
         */
        bind(property, value = undefined) {
            if (value === undefined) {
                return _.get(this.$store.state.base.bindings, property, null)
            }

            this.$store.commit('bind', [property, value])
        },
        /**
         * Detele a bound variable.
         *
         * @param {string} property
         */
        unbind(property) {
            this.$store.commit('unbind', property)
        },
        /**
         * Is property bound.
         *
         * @param {string} property
         * @return {bool}
         */
        hasBind(property) {
            return this.bind(property) !== null
        },
        /**
         * Alternate method name for hasBind().
         *
         * @param {string} property
         * @return {bool}
         */
        isBound(property) {
            return this.hasBind(property)
        }
    }
})

Vue.use({
    install(Vue) {
        window.Vuex.registerModule('base', {
            state: {
                /**
                 * Bounded variables
                 *
                 * @var {object}
                 */
                bindings: {}
            },
            mutations: {
                /**
                 * Variable bindings to the store.
                 *
                 * @param  {Object} state   Current state
                 * @param  {Array}  payload First parameter should be the binding path, second is the value
                 */
                bind(state, payload) {
                    state.bindings = Object.assign({}, state.bindings, _.set(state.bindings, payload[0], payload[1]))
                },
                /**
                 * Delete a binding.
                 *
                 * @param {Object} state
                 * @param {string} payload
                 */
                unbind(state, payload) {
                    let bindings = state.bindings

                    if (Array.isArray(payload))
                        _.get(bindings, payload[0]).splice(payload[1], 1)
                    else
                        delete _.get(bindings, payload)

                    state.bindings = Object.assign({}, bindings)
                }
            }
        })
    }
})

This allows you to call this.bind('user', user) to save a user object and this.bind('user') to retrieve it again. If it doesn't exist a null will be returned to prevent errors. Use this.hasBind('user') to check whether the use is already know:

if (! this.hasBind('user')) {
  this.bind('user', user)
}

I also created isBound() just in the sense that it sounds more correct.

I hope this brief introduction gave an idea what Vuex and State Management can do.


This article was requested from samyek sonawane

Emil Moe

Expert in Laravel and Vue backed with MySQL databases. Independent developer who does freelance and love to travel. Feel free to drop me a message.

- Emil

Write your comment…

ThankYou SooMuch Emil Moe for writing such a beautiful article on my requested topic. Really this helped me alot to understand the basics concepts of Vuex.

Happy it could help you. Let me know if you have any more questions. The bind-concept I have made is a kinda cheat around the concept as I see it, but what the heck, it makes the every day coding a lot easier and that should be the main goal :-)

And sorry for the long time it took to write ;-)

Reply to this…