Vuex 源码学习(八):揭秘模块 context 的创建及其作用
2023-11-10 12:27:41
从何而来?
在 Vuex 源码学习的上一篇章中,我们探究了 commit 与 dispatch 如何分别调用 mutation 与 action。然而,我们留下了几个悬念,涉及到我们有意略过的模块 context 属性。
在 installModule 函数中,为每个模块绑定了一个名为 context 的属性。接下来,我们将揭晓这个属性的庐山真面目,看看它是如何诞生的。
export function installModule (module, rootState, path, hot) {
const isRoot = !path.length
// 将当前模块注册到 store._modules 中
registerModule(module, rootState, path)
// store.modules 属性指向 store._modules
module.namespaced = store.modules[path] && store.modules[path].namespaced
if (module.namespaced) {
// 模块的子模块的 path 前缀
const childNamespace = path.join('.') + '.'
// 创建 context
module.context = makeLocalContext(module, rootState, path)
} else {
// 根模块的 context
const parentNamespace = path.length ? path.join('.') + '.' : ''
module.context = makeLocalContext(store, rootState, parentNamespace)
}
神秘面纱
1. 剖析 context 的生成
context 的生成由 makeLocalContext 函数负责。
export const makeLocalContext = (module, rootState, path) => {
const normalizedPath = path.reduce((memo, key) => {
memo[key] = true
return memo
}, {})
// 创建 context 对象
const local = {
// store 的 getter
getters: makeLocalGetters(module, rootState, path),
// store 的 action
dispatch: makeLocalDispatch(module, rootState),
// store 的 commit
commit: makeLocalCommit(module, rootState),
// 模块的状态
state: vuexProxy(module.state, path),
// 模块的命名空间
rootGetters: module.context ? getRootGetters(module.context) : {}
}
// 记住,在 module.namespaced 为 true 的情况下,module.context 才会存在
if (module.namespaced) {
local.namespace = path.join('.')
}
return local
}
2. context 的宝藏
通过细细品读 makeLocalContext 的代码,我们可以窥探到 context 的本质和意义。
- getters :模块内的 getter 函数,负责从模块状态中提取数据。
- dispatch :模块内的 action 函数,负责执行异步操作和状态变更。
- commit :模块内的 mutation 函数,负责直接修改模块状态。
- state :模块的状态,可以使用 vuexProxy 进行响应式代理。
- rootGetters :根模块的 getter 函数,用于访问根模块的状态。
- namespace (可选):模块的命名空间,仅在 namespaced 为 true 时存在。
大显身手
context 在 Vuex 生态系统中扮演着举足轻重的角色。
1. 动作先行:dispatch 披挂上阵
action 函数是 Vuex 中执行异步操作和状态变更的主要途径,它们被封装在 context.dispatch 中。当我们调用 context.dispatch 时,就会触发相应 action 的执行,从而实现异步操作或状态更新。
2. 提交改变:commit 一锤定音
mutation 函数是 Vuex 中直接修改模块状态的唯一途径,它们被封装在 context.commit 中。当我们调用 context.commit 时,就会触发相应 mutation 的执行,从而直接更新模块状态。
3. 洞察全局:getters 尽览全貌
getter 函数是 Vuex 中从模块状态中提取数据的手段,它们被封装在 context.getters 中。当我们调用 context.getters 时,就可以访问 getter 函数并获取所需数据。
4. 触类旁通:rootGetters 跨界取数
rootGetters 是 Vuex 中访问根模块 getter 函数的途径,它们被封装在 context.rootGetters 中。当我们调用 context.rootGetters 时,就可以访问根模块的 getter 函数并获取根模块的状态数据。
总结
Vuex 模块的 context 属性是模块与 store 交互的桥梁,它封装了模块内的 getters、dispatch、commit、state、rootGetters 和 namespace 等属性。这些属性共同构成了模块的运行环境,使模块能够与 store 进行高效通信和数据共享。
理解了 context 的创建过程和作用,我们才能更深入地理解 Vuex 模块的工作原理,从而更好地利用 Vuex 管理复杂应用的状态。