手写一个简易版vuex

159 阅读2分钟
今天学习了极客时间中大圣的`vue`课程,便在此记录一下如何手写一个`简易版vuex`

手写一个简易版vuex,首先要明白以下几点:

  • main.js中会引入store实例并use该实例
  • store文件夹中会调用vuex中的createStore创建一个store实例
  • 在store实例中,有state函数(返回一个对象,对象里是页面共享的数据),有getters、mutations、actions属性,值都为对象
  • 在需要store的vue文件里会用到vuex中的useStore 因此,我们需要在minivuex.js中定义createStoreuseStore和一个Store

minivuex.jsuseStore:

function useStore(){
    return inject(STORE)
}

使用inject是因为下面Store类中的install方法会暴露store实例 minivuex.jscreateStore:

function createStore(options){
    return new Store(options)
}

minivuex.jsStore类:

首先得定义一个方法,在main.jsuse了Store实例,在vue.js文档中有说明,一个插件若要被使用,则必须要暴露一个install方法,这个方法的第一个参数就是应用实例,通过这个方法我们可以利用vue3中的provide把store实例暴露给所有的组件。

const STORE = "__store__"
Class Store {
    constructor(){}
    install(app){
        app.provide(STORE,this);
    }
}

Store类中的属性以及方法的几个要考虑的点:

  • index.jsstore实例中的state是一个函数,因此调用后的值要赋给this.state
  • 通过useStore后得到的实例,使用getters的方法是store.getters.double.value,即它只想要拿到值,但实例中的getters配置项中都是函数,因此得因此调用完才赋给this.getters
  • commit函数与mutations中函数的联动
  • dispatch函数与actions中函数的联动 经过上述分析,Store类便可写为:
class Store {
    constructor(options) {
        this.state = reactive(options.state());
        this._mutations = options.mutations;
        this._actions = options.actions;
        this.getters = {};
        
       //遍历传进来的getters中每一个函数并执行,把值和对应属性名放入this.getters中
        Object.keys(options.getters).forEach(item => {
            const fn = options.getters[item];
            this.getters[item] = computed(() => fn(this.state));
        });
    }
    commit = (context, payload) => {
    //根据传过来的函数名去mutations中找,找到后传入state和payload后便直接执行
        const fn = this._mutations[context];
        fn && fn(this.state, payload);
    };
    dispatch = (context, payload) => {
    //根据传过来的函数名去actions中找,由于actions中参数为store实例,actions
    中是调用commit中函数来更改state的值,所以返回一个函数,参数为this和payload
        const fn = this._actions[context];
        return fn && fn(this, payload);
    };
    install(app) {
        app.provide(STORE, this);
    }
}

完整代码

minivuex.js

minivuex.png index.js

vuexindex.png 结语:第一次在掘金做记录,希望可以有所长进