preface

Through B station video and some children’s shoes article combined with Git source reading to understand the principle of vuEX implementation

Say no more, we directly on the source code

Vuex SRC directory

First take a look at vuex’s source directory. As you know, major projects are usually under SRC, so we’ll start directly from there

  • Module: Module constructor and module collection management
  • You can debug dvTools by using your plugins
  • Helpers: Integrated grammar sugarmapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers
  • Index: import file, export store, install, and above syntax sugar ↑
  • Mixin: Mixin, initialize vuex, and mount the Vue root instance
  • Store: the vuex constructor, which implements the main function of the function
  • Utils: Some tool methods

Okay, so that’s basically what this is; As we know from the official documentation, every vUE plug-in needs to have a public install method, and vuex is no exception. Step by step we analyze

Vuex entrance

src/index.js

// Import and initialize install
import { Store, install } from './store' 
// ES6 extends syntax
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers'
/ / export
export default {
  Store,
  install,
  version: '__VERSION__',
  mapState,
  mapMutations,
  mapGetters,
  mapActions,
  createNamespacedHelpers
}
Copy the code

Vue. Use (plugin), Vue. Use (), Vue. Use (), Vue. It also executes the public install method of the plug-in by default (see the official website). Ok, go to Install initialization

Vuex install method

SRC /store.js 523 lines of store.js code is a lot of code, I did not comb through the line by line, here select some important points for analysis

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 
  SRC /store.js (); /* constructor (); Vue && typeof window ! == 'undefined' && window.vue) {install(window.vue) // pass Vue root instance to install} */
  applyMixin(Vue)
}
Copy the code

Mixed with Vuex

Ok, to follow the lead, let’s go to the applyMixin method at SRC /mixins.js

export default function (Vue) { 
// Depending on the version
  const version = Number(Vue.version.split('. ') [0])
  if (version >= 2) {
    Vue.mixin({ beforeCreate: vuexInit }) // Life cycle created before mixing mount vuex
  } else {
    const _init = Vue.prototype._init // Mount on the root instance
    Vue.prototype._init = function (options = {}) {
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }
  
  // Initialize the vuex method
  function vuexInit () {
    const options = this.$options
    if (options.store) {
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
      this.$store = options.parent.$store
    }
  }
}
Copy the code

Examples of evolution

After initialization, let’s take a look at how vuex is used in daily development

import Vue from 'vue' 				// Import the vue instance
import Vuex from 'vuex' 			// Import state management vuex
Vue.use(Vuex) 				        // Install and initialize vuex
const store = new Vuex.Store({ 		        / / use
    state: {},// The location where the state is stored
    getters: {},// Get the status
    mutations: {},// Define the only way to synchronously modify the state
    actions: {},// Commit a mutaions where the state is asynchronously modified
    modules: {}// Module distribution
});
Copy the code

The store constructor initializes and integrates the corresponding properties and methods, respectively.

Initialization declaration within Store Constructor

// Initialize some parameters
 this._committing = false                             // Whether the status identifier is being submitted
 this._actions = Object.create(null)                  // Create acitons
 this._actionSubscribers = []                         // Action subscription list
 this._mutations = Object.create(null)                // Create mutations operation object
 this._wrappedGetters = Object.create(null)           // Create the getters collection object
 this._modules = new ModuleCollection(options)        // Vuex supports store-incoming modules to store analyzed modules
 this._modulesNamespaceMap = Object.create(null)      // Create the module namespace map
 this._subscribers = []                               // Subscribe to the collection of functions
 this._watcherVM = new Vue()                          // The Vue component is used for watch to monitor changes
 
// Replace the dispatch, commit methods in this to point this to store
 const store = this
 const { dispatch, commit } = this
 this.dispatch = function boundDispatch (type, payload) {
   return dispatch.call(store, type, payload)
 }
 this.commit = function boundCommit (type, payload, options) {
   return commit.call(store, type, payload, options)
 }
 / / state tree
 this.strict = strict 
 // Initialize the module
 const state = this._modules.root.state  
 // Initialize the module
 installModule(this, state, [], this._modules.root)
 // Reset the virtual VM
 resetStoreVM(this, state) // Key, key, key, the whole vuEX function implementation method
 // Load the plugins in turn
 plugins.forEach(plugin= > plugin(this))
 // Debug tool
 if (Vue.config.devtools) {
   devtoolPlugin(this)}Copy the code

Vuex core

ResetStoreVM Resets the Store instance

function resetStoreVM (store, state, hot) {
  const oldVm = store._vm  // Copy the old instance
  store.getters = {}       // Set the getters property
  const wrappedGetters = store._wrappedGetters  // Store the getters collection object
  const computed = {}
  // Run through the object wrappedGetters
  forEachValue(wrappedGetters, (fn, key) = > {
   // Add getter object properties for a computed object
   // Store.getters. Xx = store._vm[xx]; // Store.getters.
   // Add attributes in the getter for computed to facilitate the new vUE instance for store._vm
    computed[key] = partial(fn, store)
    /* export function partial (fn, arg) { return function () { return fn(arg) } } */
    // Override the get method for each getters object to create an observation
    Object.defineProperty(store.getters, key, {
      get: () = > store._vm[key],
      enumerable: true  // for local getters})})// Create an instance of Vue to hold the state and make the state responsive, the same principle as the Vue component
  // store._vm._data.$$state = store.state
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed   // Calculates properties for each property method in the wrappedGetters (getter collection object) above
  })

  // You can change the state only by committing
  if (store.strict) {
    enableStrictMode(store)
  }
}
Copy the code

conclusion

The state state of Vuex is responsive, and the state is stored in the data of the new VUE instance component by means of the data of VUE is responsive. Vuex getters realize real-time data monitoring with the help of VUE’s computing attribute computed.

Full source interpretation: reference

The Store in Vuex is essentially a Vue component without a template

Welcome to like, a little encouragement, a lot of growth

A link to the

  • Front-end visualization platform implementation scheme
  • Vue3 10 minutes takes you seconds to vue3
  • Vue template compilation principle
  • The vue constructor extends
  • How does VUEX state management work
  • Vue-router source analysis principle
  • Vue [how to listen for array changes]
  • Handwritten Vue response [object.defineProperty]
  • Vue responsive source sharing