Vuex中modules的初始化过程分析
程序员文章站
2022-04-24 09:49:17
...
modules作用
- Store作为一个数据“仓库”,存储数据,若应用变得复杂要处理的数据过多,全部放到一个state下就很麻烦。
- modules就是将store拆分成众多具有完整结构的“子仓库“,每个module也可以添加子module,从而形成一个树状结构。方便管理数据。
- 最外层的module可以理解为根 rootModule
modules的初始化
关键点
- this._modules = new ModuleCollection(options) //Store中的_modules是modules集合
- module_collection中定义register()方法来构建modules结构
- installModule(this, state, [], this._modules.root)// 初始化rootModule、注册所有子module
- makeLocalContext() // 重写dispatch和commit方法,利用namespace拼接type重新得到新type值(类似于绝对路径)
- resetStoreVM() // 将state成为响应式对象
建立模块的结构
register (path, rawModule, runtime = true) {
if (process.env.NODE_ENV !== 'production') {
assertRawModule(path, rawModule)
}
const newModule = new Module(rawModule, runtime) //新module实例 rawModule是配置项
if (path.length === 0) {
this.root = newModule //拿到根 rootModule
} else {
const parent = this.get(path.slice(0, -1))
parent.addChild(path[path.length - 1], newModule) //添加子module
}
// register nested modules
if (rawModule.modules) {//如果当前module中配置了子module 则遍历并逐一注册
forEachValue(rawModule.modules, (rawChildModule, key) => {
this.register(path.concat(key), rawChildModule, runtime)
})
}
}
得到的modules对象
安装模块
/**
@param store 当前Store的实例
@param rootState modules集合中根模块root的state数据
@param path 根模块的path为空 其他为key值
@param module对象
**/
function installModule (store, rootState, path, module, hot) {
const isRoot = !path.length
const namespace = store._modules.getNamespace(path) //根据path构造namespace => key+‘/’
// register in namespace map
if (module.namespaced) {
if (store._modulesNamespaceMap[namespace] && process.env.NODE_ENV !== 'production') {
console.error(`[vuex] duplicate namespace ${namespace} for the namespaced module ${path.join('/')}`)
}
store._modulesNamespaceMap[namespace] = module
}
// set state
if (!isRoot && !hot) {
const parentState = getNestedState(rootState, path.slice(0, -1))
const moduleName = path[path.length - 1]
store._withCommit(() => {
if (process.env.NODE_ENV !== 'production') {
if (moduleName in parentState) {
console.warn(
`[vuex] state field "${moduleName}" was overridden by a module with the same name at "${path.join('.')}"`
)
}
}
Vue.set(parentState, moduleName, module.state)
})
}
const local = module.context = makeLocalContext(store, namespace, path)//当前module的局部数据
module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
registerMutation(store, namespacedType, mutation, local) //注册mutation
})
module.forEachAction((action, key) => {
const type = action.root ? key : namespace + key
const handler = action.handler || action
registerAction(store, type, handler, local)//注册action
})
module.forEachGetter((getter, key) => {
const namespacedType = namespace + key
registerGetter(store, namespacedType, getter, local)//注册getter
module.forEachChild((child, key) => {//递归处理子模块
installModule(store, rootState, path.concat(key), child, hot)
})
}
resetStoreVM() 将state生成为响应式对象
function resetStoreVM (store, state, hot) {
const oldVm = store._vm
// bind store public getters
store.getters = {}
// reset local getters cache
store._makeLocalGettersCache = Object.create(null)
const wrappedGetters = store._wrappedGetters
const computed = {}
forEachValue(wrappedGetters, (fn, key) => {
// use computed to leverage its lazy-caching mechanism
// direct inline function use will lead to closure preserving oldVm.
// using partial to return function with only arguments preserved in closure environment.
computed[key] = partial(fn, store)
Object.defineProperty(store.getters, key, {//当我们访问store的getters时,会调用store._vm
get: () => store._vm[key],
enumerable: true // for local getters
})
})
// use a Vue instance to store the state tree
// suppress warnings just in case the user has added
// some funky global mixins
const silent = Vue.config.silent
Vue.config.silent = true
store._vm = new Vue({ //使用一个Vue实例 $$state为响应式对象,值就原state
data: {
$$state: state
},
computed
})
....
}
get state () {
return this._vm._data.$$state
}
上一篇: thinkphp获取栏目和文章当前位置的方法_php实例
下一篇: 一个简单的悬停效果(html)
推荐阅读
-
sqlserver 存储过程中的top+变量使用分析(downmoon)
-
C#中结构(struct)的部分初始化和完全初始化实例分析
-
C#中结构(struct)的部分初始化和完全初始化实例分析
-
用社会现象简单分析SEO优化过程中的操作思路
-
用实例分析Python中method的参数传递过程
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
mysql存储过程之引发存储过程中的错误条件(SIGNAL和RESIGNAL语句)实例分析
-
Linux操作系统中读取目录文件信息的过程分析
-
javascript 中select框触发事件过程的分析
-
Bootstrap初始化过程源码分析--netty客户端的启动