preface

Vuex is a state management module specially developed for Vue program. I only know it before and I don’t know why. Today, I share my thoughts on reading the source code over the weekend.

1. Prepare examples

Prepare an example to reference in main.js.

Example Vuex

Ii. Import documents

Since the current version of Vue2 is in use, we won’t talk about Vue1. Vue.use(Vuex)–>install–>applyMinxin(Vue)–>vuexInit()

ApplyMinxin (vuexInit()) is used in the Vue instance and the vuexInit() method is executed in the beforeCreate. The vuexInit() method basically adds the variable $store to the Vue instance. The logic is: if you have a store attribute on your node (mainly the root node), assign it to this.$store, otherwise fetch $store from the parent, ensuring that $store is the same in every vue instance. A simplified version of the local facsimile.

Third, the state

Analyze the characteristics of state and eliminate the module processing part in the source code. The core code is as follows:

class Store {
    constructor(options){
        // state
        this._vm=new Vue({
            data() {
                return {
                    state:options.state
                }
            }
        })

    }
    // Private variables
    get state() {return this._vm.state 
    }

}
Copy the code

In the constructor, we create an instance of Vue, bind the state in options to data, and create the state property in the class to return the data in the instance of Vue.

Four, getters

Getters are like filters in Vue that filter down the values in state and return them. Getters is also a property of the Store object, so you can copy getters from options and return its value. The Object.defineProperty method is used here. The carbon copy is as follows:

    // getters
    let getters=options.getters||{}
    this.getters={}

    Object.keys(getters).forEach(key= >{
        Object.defineProperty(this.getters,key,{
            get:() = >{
                return getters[key](this.state)
            }
        })
    })
Copy the code

I’m using the arrow function specifically for this.

Five, the mutations

Mutations stores a way to change state simultaneously. The carbon copy is as follows:

    // mutations
    let mutations=options.mutations||{}
    this.mutations={}
    Object.keys(mutations).forEach(key= >{
        this.mutations[key]=(params) = >{
            mutations[key](this.state,params)
        }
    })
Copy the code

The code above, this.mutations uses the function Coriation, passing in state as a fixed parameter.

    commit(type,params){
        this.mutations[type](params)
    }
Copy the code

Commit execution is simple.

Sixth, the actions

The overall structure of actions code is similar to mutations, but more asynchronous encapsulation.

function registerAction (store, type, handler, local) {
  const entry = store._actions[type] || (store._actions[type] = [])
  entry.push(function wrappedActionHandler (payload) {
    let res = handler.call(store, {
      dispatch: local.dispatch,
      commit: local.commit,
      getters: local.getters,
      state: local.state,
      rootGetters: store.getters,
      rootState: store.state
    }, payload)
    if(! isPromise(res)) { res =Promise.resolve(res)
    }
    if (store._devtoolHook) {
      return res.catch(err= > {
        store._devtoolHook.emit('vuex:error', err)
        throw err
      })
    } else {
      return res
    }
  })
}
Copy the code

The code used to register the action must return a Promise object. The main purpose is to be able to finish an action and proceed to the next asynchronous operation using THEN. Take a look at the implementation of Dispatch:

It can be seen that Dispatch only encapsulates a layer of mutations, and on the production version, state can also be directly modified through actions. This is not recommended for both promise.all () and devTools to keep track of changes.

The resources

  • Vuex source code analysis
  • Vuex source code: in-depth vuex action
  • Why does Vuex not recommend changing state in action