Reference Documents:

  • Vex4. x Official document

What is Vuex

Vuex is a state management mode + library developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way.

This state self-management application consists of the following parts:

  • State, the data source that drives the application;
  • Views, which declaratively map state to views;
  • Action in response to changes in state caused by user input on the view.

How Vuex works is shown below:

Simple use of vex4.x

Create a Store instance

import { createApp } from 'vue'
import { createStore } from 'vuex'

// Create a new store instance
const store = createStore({
  state () {
    return {
      count: 0}},getters: {
      double(state){
          return state.count * 2}},mutations: {
    increment (state, payload) {
      state.count++
    }
  },
  actions: {
     AsyncIncrement(state, payload){
        return new Promise((resolve, reject) = > {
            setTimeout(() = > {
                commit('someMutation', payload)
                resolve()
            }, 1000)})}})const app = createApp({ /* Root component */ })

// Install the Store instance as a plug-in
app.use(store)
Copy the code

Use by means of a composite API

Access State and Getter

import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()

    return {
      // Access state in a computed function
      count: computed(() = > store.state.count),

      // Access the getter in a computed function
      double: computed(() = > store.getters.double)
    }
  }
}
Copy the code

Access Mutation and Action

import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()

    return {
      / / using mutation
      increment: () = > store.commit('increment'),

      / / use the action
      asyncIncrement: () = > store.dispatch('asyncIncrement')}}}Copy the code

Compare vex3. x in usage

  • createstoreThe method is different from that used to be throughnew Store()To create astoreInstance. Now it’s throughcreateStoreMethod to create.
  • Vex4.x is compatible with previous use methods. But in Vue3. X, if we want to use Vuex via a composite API approach, we need to use theuseStoreThis function.

Implement a simple vex4.x;

To implement acreateStoremethods

Store is actually implemented as a Class, but instead of exposing the store Class directly, it is wrapped as a function that returns an instance directly.

import { reactive } from 'vue'

export function createStore(options){
    return new Store(options)
}

class Store{
    constructor(options){
        const store = this;
        // Use reactive to make state reactive
        store._state = reactive({data: options.state})
    }
    get state() {return this._state.data
    }
}

Copy the code

throughObject.definePropertyTo redefine getters

Define all getters passed in by the user to the Store instance’s getters property, which is called when the value is fetched

function forEachValue(obj, fn){
    Object.keys(obj).forEach(key= > fn(obj[key], key))
}

class Store{
    constructor(options){
        const store = this;

        // Use reactive to make state reactive
        store._state = reactive({data: options.state})
        
        / / save getters
        const _getters = options.getters;

        store.getters = {};

        forEachValue(_getters, function(fn, key){
            Object.defineProperty(store.getters, key, {
                get: () = > fn(store.state),
                enumerable: true}}})})Copy the code

Implement based on publish and subscribe modelmutationsactions

class Store{
    constructor(options){
        // ...
        const store = this;
        store._mutations = Object.create(null)
        const _mutations = options.mutations;

        forEachValue(_mutations, (mutation, key) = >{
            store._mutations[key] = (payload) = > {
                mutation.call(store, store.state, payload)
            }
        })
    }
    commit = (type, payload) = > {
        this._mutations[type](payload)
    }
}
Copy the code

Action is similar to mutation, except that:

  • The Action commits mutation rather than a direct state change.
  • Actions can contain any asynchronous operation

Since an action can execute asynchronous functions, the action should return a Promise instance to verify the result of dispact execution. If it is not a Promise, make it a Promise.

class Store{
    constructor(options){
        // ...
        const store = this;

        store._actions = Object.create(null)

        const _actions = options.actions;
    
        forEachValue(_actions, (action, key) = >{
            store._actions[key] = (payload) = > {
                const res = action.call(store, store.state, payload)
                if(! isPromise(res)){return Promise.resolve(res)
                }
                return res
            }
        })
    }
    dispatch = (type, payload) = > {
        this._actions[type](payload)
    }
}
Copy the code

useStore

Get the registered Store instance by inject

import {inject} from 'vue'
export function useStore(injectKey = null) {
    return inject('store')}Copy the code

install

To use Vuex in a Vue project, we need to register the store with use()


const app = createApp({ /* Root component */ })

// Install the Store instance as a plug-in
app.use(store)

Copy the code
class Store{
    install(app, injectKey){ 
        // Vue3.x createApp().use(store)
        // globally exposes a variable that exposes an instance of store
        app.provide('store')

        // Vue2.x Vue.prototype.$store = this
        // Add the $store attribute so that you can use $store.state.count directly in the template
        app.config.globalProperties.$store = this; }}Copy the code