上一篇文章已经实现了Vuex de state, getters, mutations,actions等功能juejin.cn/post/684490…
本篇需要实现 modules 也是 Vuex 重要的 modules
1. 收集模块,ModuleCollection, 先将options 的所有模块收集好,构造出想要的数据结构
// options 中的 modules 如下
modules: {
a: {
state: {
name: 'moduleA',
count: 100 },
mutations: {
addModuleA( state, payload ) {
state.count += payload
}
}
},
b: {
state: {
name: 'moduleB'
}
}
}
收集方法是为了把 modules的结构变成下面的结构
root: {// root其实就是options
_raw, // 元数据
_children: {}, // 子模块
state,//当前模块的 state
}
收集器的构造函数如下
function ModuleCollection (rootModule) {
this.register([], rootModule)
}
ModuleCollection.prototype.register = function(path, rootModule) {
let newModule = {
_raw: rootModule,
_children: {},
state: rootModule.state
}
// 判断如果是 父模块,就把模块赋值给 root
if(path.length === 0) {
this.root = newModule
}else{
// 如果有子模块
let parent = path.slice(0, -1).reduce(function(root, cur){
return root._children[ cur ]
}, this.root)
parent._children[path[path.length - 1]] = newModule
}
if(rootModule.modules) {
forEach(rootModule.modules, function(moduleName, module) {
this.register(path.concat(moduleName), module)
}).bind(this)
}
}
2.安装模块:主要是把之前的 state mutations getters actions注册到 store中
// 安装模块
function installModule( store, state, path, rootModule ) {
// 安装模块的 state
if( path.length > 0 ) {
let parent = path.slice(0, -1).reduce(function(state, cur) {
return state[cur]
}, state)
Vue.set(parent, path[path.length - 1], rootModule.state )
}
// 需要递归 将结果挂载 getters, mutations, actions
var getters = rootModule._raw.getters
if( getters ) {
// 给 store 增加了getters 属性
forEach(getters, function(key, value) {
Object.defineProperty(store.getters, key, {
enumerable: true,
configurable: true,
get: function() {
return value( rootModule.state )
}
})
})
}
// 处理mutations
var mutations = rootModule._raw.mutations
if( mutations ) {
forEach(mutations, function(key, value) {
store.mutations[key] = store.mutations[key] || []
store.mutations[key].push(function(payload) {
value(rootModule.state, payload )
})
})
}
// 处理actions
var actions = rootModule._raw.actions
if( actions ) {
forEach( actions, function(key, value) {
store.actions[key] = store.actions[key] || []
store.actions[key].push( function(payload) {
value(store, payload)
})
})
}
if( rootModule._children ) {
forEach( rootModule._children, function(moduleName, module) {
installModule( store, state, path.concat(moduleName), module )
})
}
}