Vuex源码中module的register方法
register 翻译为登记 ,可以理解为 每一个module都进行登记
Vuex中的源码module-collection中两个方法
class ModuleCollection {
// rawRootModule 为 Vue的 options属性
constructor (rawRootModule) {
// register root module (Vuex.Store options)
this.register([], rawRootModule, false)
}
get (path) {
return path.reduce((module, key) => {
return module.getChild(key)
}, this.root)
}
// path 为空数组 [] rawModule 为传入的options
register (path, rawModule, runtime = true) {
/*
Module创建对象主要参数为 子元素 module模块中内容 状态
this._children = Object.create(null)
this._rawModule = rawModule
const rawState = rawModule.state
*/
const newModule = new Module(rawModule, runtime)
if (path.length === 0) {
this.root = newModule
} else {
const parent = this.get(path.slice(0, -1))
parent.addChild(path[path.length - 1], newModule)
}
// register nested modules
if (rawModule.modules) {
forEachValue(rawModule.modules, (rawChildModule, key) => {
this.register(path.concat(key), rawChildModule, runtime)
})
}
}
}
模拟实现
let obj = {
module:{
a:{
state:{
a:"a"
},
module:{
c:{
state:"c",
}
}
},
b:{
state:{
b:"b"
}
}
},
state:{
root:"123"
}
}
/*
改为 格式
let root = {
// 也就是 options
_raw:rootModule,
// 状态
state:{},
// 子module
_children:{}
}
*/
class ModuleCollect{
constructor(options) {
// 开始创建为指定格式
// 参数1 为属性名数组对象
this.register([],options);
}
// 接收 属性名数组,和对应的option 参数列表
register(moduleNameList,moduleOptions){
let newModule = {
_raw:moduleOptions,
state:moduleOptions.state,
_children:{}
}
// 判断list身上是否是空的 如果是空的就让根module为newModule
if(moduleNameList.length === 0){
this.root = newModule;
}else{
// 查找对应父属性 ,在父属性中每一个子属性改为 newModule 样式
let parent = moduleNameList.slice(0,-1).reduce((root,current)=>{
// 返回moduleNameList中 倒数第二个元素的属性
// 使用reduce递归去找 找到倒数第二个元素
return root._children[current];
},this.root)
// 父元素的children数组里面的最后一个元素 为newModule
parent._children[moduleNameList[moduleNameList.length-1]] = newModule;
}
if(moduleOptions.module){
Object.keys(moduleOptions.module).forEach((item)=>{ // item 分别为 a,c,b
// 递归调用
// moduleNameList 分别为 item为a时 [],item为c时 [a],item为b时 []
// moduleNameList.concat(item) [a] [a,c] [b]
this.register(moduleNameList.concat(item),moduleOptions.module[item]);
})
}
}
}
console.log(new ModuleCollect(obj))
register的原理 就是将传递的不规则参数,改为指定格式用于后续用途 Vuex中大多数使用该种递归方式实现递归