Vuex source

Source code analysis

A simple example

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Copy the code

1. Registration of Vuex

This method calls the install method of the plugin. Take a look at what the install method does. As you can see from index.js, the install method is thrown in store.js

let Vue // bind on install

export function install (_Vue) {
  if (Vue && _Vue === Vue) {
    if(process.env.NODE_ENV ! = ='production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.')}return
  }
  Vue = _Vue
  applyMixin(Vue)
}
Copy the code

We declare a Vue variable, which is assigned to the install method. This provides the current scope with a Vue. The advantage of this is that we don’t need to import Vue from ‘Vue’, but we can also write this and ask the packaging tool not to package it. Instead, it points to the Vue provided by the developer, such as externals for webpack, which is not expanded here. Install checks whether the Vue has been assigned a value to avoid secondary installation. Then call the applyMixin method as follows

// applyMixin
export default function (Vue) {
  const version = Number(Vue.version.split('. ') [0])

  if (version >= 2) {
    Vue.mixin({ beforeCreate: vuexInit })
  } else {
    // override init and inject vuex init procedure
    // for 1.x backwards compatibility.
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {}) {
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }

  /** * Vuex init hook, injected into each instances init hooks list. */

  function vuexInit () {
    const options = this.$options
    // store injection
    // When we execute new Vue, we need to provide the store field
    if (options.store) {
      // If root, bind store to this.$store
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
      // Get $store from parent
      // So that all components share one store instance
      this.$store = options.parent.$store
    }
  }
}


Copy the code

X and 1.x have different hooks. If 2.x uses beforeCreate, 1.x uses _init. When we start a Vue application by executing new Vue, we need to give the store field, the root component gets the store from here, the child component gets the store from the parent component, and so on, layer by layer, so that all components have the Store property, so that we can pass this. Store property in any component, This allows us to access store from any component through the this.store property

So let’s continue with the example

// store.js
export default new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    evenOrOdd: state= > state.count % 2= = =0 ? 'even' : 'odd'
  },
  actions:  {
    increment: ({ commit }) = > commit('increment'),
    decrement: ({ commit }) = > commit('decrement')},mutations: {
    increment (state) {
      state.count++
    },
    decrement (state) {
      state.count--
    }
  }
})

Copy the code