手写简易版 Vuex
简易版 Vuex,直接引入也可以用
js
let Vue; // 插件全局使用
class Store {
constructor(options) {
// 保存用户定义的 mutations,actions,getters
this._mutations = options.mutations;
this._actions = options.actions;
this._getters = options.getters;
// 更正 this 指向
this.commit = this.commit.bind(this);
this.dispatch = this.dispatch.bind(this);
// 实现 this.getters
const computed = {};
const store = this;
this.getters = {};
for (let key in this._getters) {
// 用户定义的 getters 方法
const fn = store._getters[key];
// 无参数形式访问 this.getters.key
computed[key] = () => fn(store.state);
// 响应式只读属性
Object.defineProperty(this.getters, key, {
get: () => store._vm[key],
});
}
// Vue 默认会把 data 遍历处理成响应式
this._vm = new Vue({
data: {
$$state: options.state,
},
computed,
});
}
// es6 get set
get state() {
return this._vm._data.$$state;
}
set state(v) {
console.error('use replaceState to reset state');
}
commit(type, payload) {
const entry = this._mutations[type];
if (!entry) console.error('unknow mutations type');
entry(this.state, payload);
}
dispatch(type, payload) {
const entry = this._actions[type];
if (!entry) console.error('unknow actions type');
entry(this, payload);
}
}
// Vue.use 方式 install.apply(this,[this,...])
function install(_Vue) {
Vue = _Vue; //保存参入的 Vue,不用引入也能使用
// 全局混入,挂载 $store,延迟下面逻辑到 store 被添加到 new vue 选项时才执行
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
}
},
});
}
export default { Store, install };