Implement simple Vuex

Implement simple Vuex

Implement simple Vuex

introduce

The purpose of this paper is to realize a simple version of Vuex for learning, and it is also a summary and review of learning from online classes. The content is easy to implement. There are many shortcomings. Please communicate more.

Content splitting

  • Implement Store class

    • Save constructor parameters separately

    • Maintain a responsive state

    • Implement the commit method and the dispatch method

    • Implement getters

  • Implement the install method

    • Mount $store

Plug in test

First, modify the import information of the plug-in for viewing the output information during the implementation process, so as to find errors and problems.

  • Copy the store folder, name it ksstore, and modify main JS
// Before modification
import store from "./store";
// After modification
import store from "./kstore";
  • Create kvuex JS and modify ksstore / index JS
// Before modification
import Vuex from "vuex";
// After modification
import Vuex from "./kvuex.js";

At this point, you can modify it and start the implementation of the plug-in.

Plug in implementation

Plug in build

First, build a plug-in shelf and split it according to the above content

  • Principal Store class

  • install method

You can get the following code

class Store{}
fucntion install(){}
export default {Store,install}

It is different from the implementation of KVUE router because vuex is different from vueruter in use.

// vue-router
const router = new VueRouter({...})
export default router
// vuex
export default new Vuex.Store({})

So what vuex wants to export is the object containing the Store class and the install method.

Implementation of install method

In the install method, the main task is

  • Construction method of Vue in saved parameters

  • Mount $store in mixin mode

The task content is similar to KVUE router and will not be repeated.

let Vue;
function install(_Vue) {
  Vue = _Vue;

  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store;
      }
    },
  })
}

Store class implementation

In this area, the main tasks are:

  • Save constructor parameters separately

  • Maintain a responsive state

  • Implement the commit method and the dispatch method

  • Implement getters

Save constructor parameters separately

In fact, this task belongs to optimization content, which is just for the convenience of code writing.

constructor(options) {
    this._mutations = options.mutations
    this._actions = options.actions
}

In this way, the parameters are saved separately, which is more convenient when implementing the commit and dispatch methods.

Maintain a responsive state

Students who have used vuex know that the data in vuex is the same as the data in the page. After changes, they will be displayed on the page immediately, that is, they are all responsive data. Therefore, in vuex, the data in state should be processed responsively.

But there are two points to note

  • Responsive data but cannot be proxied

    • Data in state cannot pass this XXX can only be accessed through this$ store. state. XXX access. Therefore, when responding to state data, you should also prevent state data from being proxied to Vue instances.
  • state data cannot be modified directly

    • Actually through this$ store. state. XXX can be modified directly, but it is not recommended. The reasons are as follows:
      Vuex source code uses the watch function to monitor the data in this state. Note that this function is flawed. If the value in state is an array, listening cannot be triggered when the array is modified by subscript.
    • As far as possible, we can only modify by submitting the methods in changes through the commit method, so we need to set the get and set properties
this._vm = new Vue({
    data: {
      $$state: options.state  
      // Plus two $, the data will be processed in a responsive manner, but it will not be proxied if it is not attached to the Vue instance
    }
})
get state(){
  return this._vm._data.$$state;
}
set state(v){
console.log('please use replaceState to reset state');
}

Implement the commit and dispatch methods

  • The commit method is used to submit change data: commit(type,payload)
constructor(){
  // Binding context
  this.commit = this.commit.bind(this);
}
commit(type, payload) {
    // Get the function corresponding to type in the variations option and call
    const fn = this.$options.mutations[type];
    if (!fn) {
      console.error(`${type}Method does not exist`);
      return;
    }
    fn(this, this.state, payload);
}

  • The dispatch method is used to trigger asynchronous operations in actions: dispatch(type,payload)
constructor(){
  // Binding context
  this.dispatch = this.dispatch.bind(this);
}
dispatch(type, payload) {
    // Get the function corresponding to type in the variations option and call
    const fn = this.$options.actions[type];
    if (!fn) {
      console.error(`${type}Method does not exist`);
      return;
    }
    fn(this, payload);
}

Implement getters

Here, in order to make getters have the effect of caching, we implement getters by calculating attributes.

The caching effect here can also be avoided. The basic principle is circular options Getters, via object The defineproperty method adds a property to the empty getters object.

 constructor(options) {
    this._wrapGetters = options.getters;
    this.getters = {};
    const computed = {};
    const store = this;
    Object.keys(this._wrapGetters).forEach(key => {
      const fn = store._wrapGetters[key];
      computed[key] = function () {
        return fn(store.state)
      }
      Object.defineProperty(store.getters, key, {
      // If you do not need to use calculated properties, store_ VM [key] can be changed to fn(store.state)
        get: () => store._vm[key]
      })
    })
    // state
    this._vm = new Vue({
      data: {
        $$state: options.state
      },
      computed
    })
   
}

Keywords: Vue

Added by bamfon on Sat, 01 Jan 2022 04:35:46 +0200