今天学习了极客时间中大圣的`vue`课程,便在此记录一下如何手写一个`简易版vuex`。
手写一个简易版vuex,首先要明白以下几点:
- 在
main.js中会引入store实例并use该实例 - 在
store文件夹中会调用vuex中的createStore创建一个store实例 - 在store实例中,有
state函数(返回一个对象,对象里是页面共享的数据),有getters、mutations、actions属性,值都为对象 - 在需要store的vue文件里会用到
vuex中的useStore因此,我们需要在minivuex.js中定义createStore、useStore和一个Store类
minivuex.js中useStore:
function useStore(){
return inject(STORE)
}
使用inject是因为下面Store类中的install方法会暴露store实例
minivuex.js中createStore:
function createStore(options){
return new Store(options)
}
minivuex.js中Store类:
首先得定义一个方法,在main.js中use了Store实例,在vue.js文档中有说明,一个插件若要被使用,则必须要暴露一个install方法,这个方法的第一个参数就是应用实例,通过这个方法我们可以利用vue3中的provide把store实例暴露给所有的组件。
const STORE = "__store__"
Class Store {
constructor(){}
install(app){
app.provide(STORE,this);
}
}
Store类中的属性以及方法的几个要考虑的点:
index.js中store实例中的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
index.js
结语:第一次在掘金做记录,希望可以有所长进