module-collection.js
import { forEach } from '../util'
import Module from './module';
class ModuleCollection {
constructor(options) {
// 对数据进行格式化操作
// this.root = {
// _raw: '用户定义的模块',
// state: '当前模块自己的状态',
// _children: { // 孩子列表
// a: {
// _raw: '用户定义的模块',
// state: '当前模块自己的状态',
// _children: { // 孩子列表
// e: {}
// }
// },
// c: {
// }
// }
// }
this.root = null;
this.register([], options); // 创建一个栈结构,为了记录父子关系(上一级为下一级的父亲)
}
getNamespace(path) {
// [a,b,c]
// 如果 a、b、c 都写了 namespace,则 namespace 为 'a/b/c'
// 如果 a、b、c 都没写 namespace,则 namespace 为 ''
let root = this.root
let ns = path.reduce((ns, key) => { // this.root.c.namespace
let module = root.getChild(key);
root = module;
return module.namespaced ? ns + key + '/' : ns
}, '');
return ns;
}
register(path, rawModule) {
let newModule = new Module(rawModule)
rawModule.newModule = newModule; // 自定义属性
if (path.length == 0) {
this.root = newModule
} else {
// 找父亲:从根节点依次向下查找
let parent = path.slice(0, -1).reduce((memo, current) => {
return memo.getChild(current)
}, this.root);
parent.addChild(path[path.length - 1], newModule);
// 根据当前注册的key ,将他注册到对应的模块的儿子处
}
// 注册完毕当前模块,在进行注册根模块
// 用户进行了 modules 模块化操作
if (rawModule.modules) {
forEach(rawModule.modules, (module, key) => {
// 递归遍历,将 modules 格式化成上述的树形结构
// 此处 path.concat(key) 会返回一个新 [],不会存在引用问题(此处是深度优先遍历)
this.register(path.concat(key), module);
})
}
}
}
export default ModuleCollection
store.js
import { Vue } from './install'
import ModuleCollection from './module/module-collection';
import { forEach } from './util';
function installModule(store, rootState, path, module) { // a/b/c/d
// 需要循环当前模块的
// 获取moduleCollection类的实例
let ns = store._modules.getNamespace(path);
// module.state => 放到rootState对应的儿子里
if (path.length > 0) { // 儿子模块
// 需要找到对应父模块,将状态声明上去
// {name:'zf',age:'12',a:aState}
let parent = path.slice(0, -1).reduce((memo, current) => {
return memo[current];
}, rootState);
// 对象新增属性不能导致重新更新视图
Vue.set(parent, path[path.length - 1], module.state);
}
module.forEachGetter((fn, key) => {
store.wrapperGetters[ns + key] = function () {
return fn.call(store, module.state);
}
});
module.forEachMutation((fn, key) => { // {myAge:[fn,fn]}
store.mutations[ns + key] = store.mutations[ns + key] || [];
store.mutations[ns + key].push((payload) => {
return fn.call(store, module.state, payload)
})
});
module.forEachAction((fn, key) => {
store.actions[ns + key] = store.actions[ns + key] || [];
store.actions[ns + key].push((payload) => {
return fn.call(store, store, payload)
})
});
module.forEachChildren((child, key) => {
installModule(store, rootState, path.concat(key), child);
});
}
class Store {
constructor(options) {
// 对用户的模块进行整合
// 当前格式化完毕的数据 放到了this._modules里
this._modules = new ModuleCollection(options); // 对用户的参数进行格式化操作
this.wrapperGetters = {}
this.getters = {}; // 我需要将模块中的所有的getters,mutations,actions进行收集
this.mutations = {};
this.actions = {};
const computed = {};
// 没有namespace的时候 getters都放在根上 ,actions,mutations 会被合并数组
let state = options.state;
installModule(this, state, [], this._modules.root);
forEach(this.wrapperGetters, (getter, key) => {
computed[key] = getter;
Object.defineProperty(this.getters, key, {
get: () => this._vm[key]
})
});
this._vm = new Vue({
data: {
$$state: state
},
computed
});
console.log(this.getters, this.mutations, this.actions)
}
get state() {
return this._vm._data.$$state
}
commit = (mutationName, payload) => { // 发布
this.mutations[mutationName] && this.mutations[mutationName].forEach(fn => fn(payload))
}
dispatch = (actionName, payload) => {
this.actions[actionName] && this.actions[actionName].forEach(fn => fn(payload))
}
}
// state getters action mutation (modules 分层)
export default Store;
打赏作者
您的打赏是我前进的动力
微信
支付宝
vuex 中的模块收集、模块安装、模块实现
上一篇
评论