如果你還不知道Vuex是怎麼安裝的,請移步Vuex原始碼學習(三)install都做了哪些事情
整合模組
這一節該分析模組的是怎麼被整合的,以及要整合成什麼樣子。
在Vuex的constructor中比較靠前的位置有這麼兩行程式碼,_modules屬性是ModuleCollection的例項物件,之後 _modules屬性被頻繁使用,這塊就是對Vuex的模組進行了一次整合,整合出一個可以被使用的 _modules,而_moduleNamespaceMap是一個空物件
該怎麼整合模組?
先看一下我們我們專案中Store的結構 store/index.js
moduleList:moduleSet:
結構就是這樣的
在以上程式碼中的modules下的資料,我都稱它是偽(未加工)模組,因為它還不具有模組的功能。 當我們例項化Vuex.Store這個類的時候接收的引數options就會直接交給moduleCollection來處理。引數options是什麼呢?就是上面圖中這樣結構的資料, 想要處理成什麼樣子? 下面看一下ModuleCollection是怎麼處理的export default class ModuleCollection {
constructor (rawRootModule) {
// register root module (Vuex.Store options)
// 註冊模組並連結
this.register([], rawRootModule, false)
}
...
register (path, rawModule, runtime = true) {
if (process.env.NODE_ENV !== 'production') {
// 不符合規則的模組會報錯。
assertRawModule(path, rawModule)
}
// 建立一個模組
const newModule = new Module(rawModule, runtime)
if (path.length === 0) {
this.root = newModule
} else {
// path.slice(0,-1)就可以拿到父模組的path。
// get方法可以根據path來找到對應的模組。
const parent = this.get(path.slice(0, -1))
// 將子模組掛載到父模組上
parent.addChild(path[path.length - 1], newModule)
}
// register nested modules
if (rawModule.modules) {
// 遍歷每個模組的modules(目的是獲取所有子模組)
forEachValue(rawModule.modules, (rawChildModule, key) => {
// 為什麼要path.concat(key)?
// 依次註冊子模組。
this.register(path.concat(key), rawChildModule, runtime)
})
}
}
}
複製程式碼
在Vuex與vue-router的原始碼中,命名變數是很有規律的, 在開發人員使用這兩個框架的時候,傳遞進去的引數,在使用時命名的變數名都是raw開頭的,代表是未經過加工的。
將未經過加工的偽模組處理成真正可以使用的模組。
在初始化的時候直接開始註冊模組, moduleCollection的這個類的任務是把生成的模組合理的連結起來,而模組的生成交給了Module這個類。
所以register方法就是把根模組以及所有的子模組從一個偽(未加工)模組變成一個真正的模組並且連結起來。 遍歷樹形結構用什麼方法? 遞迴!
register都做了什麼?
- 篩選出不符合規則的模組,報錯提示。
- 將偽(未加工)模組加工成一個真正的模組。
- 將加工好的模組掛載在它的父模組上。
- 如果這個模組有modules屬性(模組有自己的子模組)讓每個子模組重複以上操作
遞迴的出口:rawModule.modules為false(模組沒有子模組) ,也就是每個模組都沒有子模組需要註冊了,那就代表全部加工與連結完畢。
分析register的三個引數
register接收三個引數,path、rawModule、hot。
hot這個引數目前看來不關鍵。
rawModule是偽(未加工)模組
那path的作用是什麼呢?
path的作用很大,大家類比下前端頁面的dom樹的Xpath,如果我想知道這個節點的位置,需要知道這個父節點的位置,然後一層一層的向上知道根結點,有了Xpath就可以直接找到這個節點,
Vuex也是一樣的想知道某個模組的位置,只需要提供根結點到他的一個path,path按順序儲存著根模組到它本身的所有祖先模組(根模組沒有名字,又不能把第一個放一個空,所以path裡 面沒有根模組),在每次註冊的時候,這個模組有子模組,就把它的path加上(concat)子模組的名字,在子模組執行register方法時,path就比它的父模組多一個父模組的名字,所以根模組註冊的時候傳入path就是[](空陣列)了。
ModuleCollection的get方法可以根據path來獲取指定的模組,在掛載的時候十分有用,
,使用reduce的方法,按照陣列的順序,一層一層的找目標模組。path對以後要講的設定名稱空間也很有幫助。
總結
- ModuleCollection這個類,主要完成了模組的連結與整合,生成模組的任務交給了Module這個類。
- 模組的連結與整合通過遞迴完成。
- path可以讓moduleCollection快速找到對應模組。
下一章講述生成的module具體可以做什麼