// installModule(this, state, [], this._modules.root)
function installModule(store, rootState, path, module, hot) {
// 判断是否为 rootModule
const isRoot = !path.length
// 获取 namespace,root 没有 namespace
// 对于 modules: {a: moduleA} 来说
// namespace = 'a/'
const namespace = store._modules.getNamespace(path)
// 为 namespace 缓存 module
if (module.namespaced) {
store._modulesNamespaceMap[namespace] = module
}
// 设置 state
if (!isRoot && !hot) {
// 以下逻辑就是给 store.state 添加属性
// 根据模块添加
// state: { xxx: 1, a: {...}, b: {...} }
const parentState = getNestedState(rootState, path.slice(0, -1))
const moduleName = path[path.length - 1]
store._withCommit(() => {
Vue.set(parentState, moduleName, module.state)
})
}
// 该方法其实是在重写 dispatch 和 commit 函数
// 你是否有疑问模块中的 dispatch 和 commit
// 是如何找到对应模块中的函数的
// 假如模块 A 中有一个名为 add 的 mutation
// 通过 makeLocalContext 函数,会将 add 变成
// a/add,这样就可以找到模块 A 中对应函数了
const local = (module.context = makeLocalContext(store, namespace, path))
// 以下几个函数遍历,都是在
// 注册模块中的 mutation、action 和 getter
// 假如模块 A 中有名为 add 的 mutation 函数
// 在注册过程中会变成 a/add
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)
})
// 这里会生成一个 _wrappedGetters 属性
// 用于缓存 getter,便于下次使用
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)
})
}