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
- Actually through this$ store. state. XXX can be modified directly, but it is not recommended. The reasons are as follows:
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 }) }