首先确定需求,vuex的功能是实现状态集中管理,其中需要实现的内容
- store
- state
- mutations
- actions
- getters
- 响应式
代码实现
let Vue; class Store { constructor(options) { // 同样对vue强依赖 使用vue实现响应数据的更新 this.state = new Vue({ data: options.state }); this.mutations = options.mutations; this.actions = options.actions; options.getters && this.handleGetters(options.getters); } //为什么没有定义到构造器内部?因为每个实例可以公用这些方法 // 为mutations actions getters为每个实例化单独享有的 // 声明为箭头函数,why?为了直接可以使用this.mutations,this.state commit = (type, arg) => { this.mutations[type](this.state, arg); }; dispatch(type, arg) { this.actions[type]( { commit: this.commit, state: this.state }, arg ); } // getters为参数 而this.getters是实例化的 handleGetters(getters) { this.getters = {}; // 遍历getters所有key Object.keys(getters).forEach(key => { // 为this.getters定义若干属性,这些属性是只读的 // $store.getters.score Object.defineProperty(this.getters, key, { get: () => { return getters[key](this.state); } }); }); } } function install(_Vue) { Vue = _Vue; Vue.mixin({ beforeCreate() { if (this.$options.store) { Vue.prototype.$store = this.$options.store; } } }); } export default { Store, install };
要点分析
vue使用外来依赖
因为插件本身就使用了传入的vue,因此尽量不要内部定义vue,直接从从参数获取。
mixin
是否需要混入,混入本身很好用,但使用混入的最大前提是需要拿到组件的实例,如果你不希望或者不用拿到,那么直接定义到Vue的原型上即可。
getter为什么是只读的
通过Object.defineProperty实现定义一个get函数,让其变成只读的
箭头函数
当你需要使用外部环境,并且在组件实例的使用中不受影响的话,你就因该考虑箭头函数。