module與moduleCollection你必定要會啊!Vuex源碼學習(五)加工後的modulevue
在組件中使用vuex的dispatch和commit的時候,咱們只要把action、mutation註冊好,經過dispatch、commit調用一下方法名就能夠作到。vuex
vue組件內segmentfault
//in vue component this.$store.commit('setName',{name : 'xLemon'}); this.$store.commit('list/setName',{name : 'xLemon'});
vuex的mutation中數組
// in mutation.js export const setName = function(state,payload){ state.name = payload.name; }
// in list mutation.js 在名爲list的模塊下的mutation(有本身的命名空間) export const setName = function(state,payload){ state.name = payload.name; }
咱們傳遞的只是一個字符串,commit是如何找到註冊mutation時的同名方法的呢?有命名空間的這種mutation是如何被找到而且執行的呢?函數
上源碼學習
屬性的意義this
被註冊的action和mutation如何被放到對應的屬性中的呢?spa
輪到installModule函數要出馬了。3d
installModule的意義是初始化根模塊而後遞歸的初始化全部模塊,而且收集模塊樹的全部getters、actions、mutations、以及state。
看一下installModule的代碼,installModule並非在類的原型上,並不暴露出來,屬於一個私有的方法,接收五個參數。code
function installModule (store, rootState, path, module, hot) { const isRoot = !path.length // 獲取全名 const namespace = store._modules.getNamespace(path) // register in namespace map if (module.namespaced) { // 設置命名空間對照map store._modulesNamespaceMap[namespace] = module //console.log(store._modulesNamespaceMap); } // set state if (!isRoot && !hot) { const parentState = getNestedState(rootState, path.slice(0, -1)) const moduleName = path[path.length - 1] // 把子模塊的state(數據)綁定到父模塊上(按照層級) store._withCommit(() => { Vue.set(parentState, moduleName, module.state) }) } const local = module.context = makeLocalContext(store, namespace, path) // 使用模塊暴露出來的方法來註冊mutation、action、getter module.forEachMutation((mutation, key) => { const namespacedType = namespace + key registerMutation(store, namespacedType, mutation, local) }) module.forEachAction((action, key) => { const type = action.root ? key : namespace + key const handler = action.handler || action registerAction(store, type, handler, local) }) module.forEachGetter((getter, key) => { const namespacedType = namespace + key registerGetter(store, namespacedType, getter, local) }) module.forEachChild((child, key) => { installModule(store, rootState, path.concat(key), child, hot) }) }
這個函數雖然只有40多行,但處於一個承上啓下的關鍵點,這一章只會分析如何收集mutation與action其他的內容會再下一章講述。
installModule首先獲取一下這個模塊的命名(我稱之爲全名)
依賴_modules(ModuleCollection實例對象)的getNamespace方法。
根據模塊的path,path有從根結點到當前節點這條路徑上按順序排序的全部模塊名(根結點沒有模塊名,並無設置在path,因此根模塊註冊時是個空數組,他的子模塊的path就是[子模塊的名字])。那麼Vuex如何整理模塊名的呢?
效果:
爲何會是這樣?分析一下代碼
getNamespace (path) { let module = this.root //根模塊 return path.reduce((namespace, key) => { //根模塊的path是個空數組不執行 // path的第一項是根模塊的兒子模塊。 // 獲取兒子模塊 而且將替換module (path的下一項就是兒子模塊中的子模塊了) // 下次累加 就是這個module(輪到子模塊了)去找它(子模塊)的子模塊 module = module.getChild(key) // 查看兒子模塊是否是設置了命名空間 //若是設置了這個模塊的全名就增長本身的模塊名和一個'/'分割後面的模塊名, //沒有的話返回一個'', // reduce累加能夠把這個名稱進行累加 return namespace + (module.namespaced ? key + '/' : '') }, '') }
獲取完模塊的全名了,以後咱們看一下這兩個函數
在上一章節module提供了遍歷本身內部的action、mutation的方法。
module.forEachMutation((mutation, key) => { const namespacedType = namespace + key registerMutation(store, namespacedType, mutation, local) }) module.forEachAction((action, key) => { const type = action.root ? key : namespace + key const handler = action.handler || action registerAction(store, type, handler, local) })
const namespacedType = namespace + key
這句話 就是拼接出真正的mutation、action的名字
模塊全名+mutation/action的名字。也就是一開始我舉例的list/setName是這個mutation的全名(被調用的時候用)
this.$store.commit('list/setName',{name : 'xLemon'});
名稱已經獲取到了,下一步怎麼辦?
把這些函數按照對應名字放到以前說的_actions、_mutations屬性中啊
小彩蛋 設置兩個不一樣模塊的同名mutation(全名同樣哦)這兩個mutation都會執行,action也是同樣的。
action和mutation在被dispatch和commit調用前,
下一章:咱們討論action和mutation如何被調用的(調用篇)。