Vuex源碼中module的register方法
register 翻譯為登記 ,可以理解為 每一個(gè)module都進(jìn)行登記
Vuex中的源碼module-collection中兩個(gè)方法
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 為空數(shù)組 [] rawModule 為傳入的options
register (path, rawModule, runtime = true) {
/*
Module創(chuàng)建對象主要參數(shù)為 子元素 module模塊中內(nèi)容 狀態(tài)
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)
})
}
}
}
模擬實(shí)現(xiàn)
let obj = {
module:{
a:{
state:{
a:"a"
},
module:{
c:{
state:"c",
}
}
},
b:{
state:{
b:"b"
}
}
},
state:{
root:"123"
}
}
/*
改為 格式
let root = {
// 也就是 options
_raw:rootModule,
// 狀態(tài)
state:{},
// 子module
_children:{}
}
*/
class ModuleCollect{
constructor(options) {
// 開始創(chuàng)建為指定格式
// 參數(shù)1 為屬性名數(shù)組對象
this.register([],options);
}
// 接收 屬性名數(shù)組退唠,和對應(yīng)的option 參數(shù)列表
register(moduleNameList,moduleOptions){
let newModule = {
_raw:moduleOptions,
state:moduleOptions.state,
_children:{}
}
// 判斷l(xiāng)ist身上是否是空的 如果是空的就讓根module為newModule
if(moduleNameList.length === 0){
this.root = newModule;
}else{
// 查找對應(yīng)父屬性 ,在父屬性中每一個(gè)子屬性改為 newModule 樣式
let parent = moduleNameList.slice(0,-1).reduce((root,current)=>{
// 返回moduleNameList中 倒數(shù)第二個(gè)元素的屬性
// 使用reduce遞歸去找 找到倒數(shù)第二個(gè)元素
return root._children[current];
},this.root)
// 父元素的children數(shù)組里面的最后一個(gè)元素 為newModule
parent._children[moduleNameList[moduleNameList.length-1]] = newModule;
}
if(moduleOptions.module){
Object.keys(moduleOptions.module).forEach((item)=>{ // item 分別為 a,c晚吞,b
// 遞歸調(diào)用
// moduleNameList 分別為 item為a時(shí) [],item為c時(shí) [a]灸撰,item為b時(shí) []
// moduleNameList.concat(item) [a] [a,c] [b]
this.register(moduleNameList.concat(item),moduleOptions.module[item]);
})
}
}
}
console.log(new ModuleCollect(obj))
register的原理 就是將傳遞的不規(guī)則參數(shù)挪捕,改為指定格式用于后續(xù)用途 Vuex中大多數(shù)使用該種遞歸方式實(shí)現(xiàn)遞歸