西宁 网站建设,设计网站专题页包括那些项目,网站建设的工作在哪里找客户资源,百度网站提交地址一#xff0c;前言
上一篇#xff0c;主要介绍了 Vuex 模块安装的实现#xff0c;针对 action、mutation、getter 的收集与处理#xff0c;主要涉及以下几个点#xff1a;
Vuex 模块安装的逻辑#xff1b;Vuex 代码优化#xff1b;Vuex 模块安装的实现#xff1b;Vue…一前言
上一篇主要介绍了 Vuex 模块安装的实现针对 action、mutation、getter 的收集与处理主要涉及以下几个点
Vuex 模块安装的逻辑Vuex 代码优化Vuex 模块安装的实现Vuex 初始化流程梳理
本篇继续介绍 Vuex 模块相关概念Vuex 的 State 状态安装 二前文梳理
前面通过依赖收集对 options 的格式化处理得到了“模块树”又通过依赖安装对“模块树”进行递归操作从根模块开始将对应的 getter、mutation、action 统一放入 Store 类的 this._actions、this._mutations、this._wrappedGetters 中
Vuex 的初始化流程如下
当项目引用并注册 vuex 插件时即 Vuex.use(vuex)将执行 Vuex 插件中的 install 方法install 方法接收外部传入的 Vue 实例并通过 Vue.mixin 实现 store 实例的全局共享项目中通过 new Vuex.Store(options) 配置 vuex 并完成 store 状态实例的初始化在 Store 实例化阶段时将会对 options 选项进行处理此时完成 Vuex 模块收集和安装操作在 new Vue 初始化时将 store 实例注入到 vue 根实例中此时的 store 实例已实现全局共享
接下来继续在 installModule 方法中处理“模块树”的 State 状态 三Vuex 模块安装-State状态安装
1State 状态的安装逻辑
对“模块树”中状态的安装就是将所有子模块上的 State 状态挂载到对应父模块的 State 状态上
处理范围子模块即 path.length 0时执行状态安装逻辑处理逻辑将子模块的状态 module.state挂载到其父模块的状态上
2引出问题
所以首先需要解决以下两个问题
问题 1如何找到当前子模块对应的父模块问题 2如何将子模块状态挂载到父模块的状态上
3问题 1如何找到当前子模块对应的父模块
从“模块树”中查找一个子模块对应的父模块这个逻辑其实在模块收集时就已经写过了
/*** 安装模块* param {*} store 容器* param {*} rootState 根状态* param {*} path 所有路径* param {*} module 格式化后的模块对象*/
const installModule (store, rootState, path, module) {// 处理子模块将子模块上的状态添加到对应父模块的状态中if(path.length 0){// 从根状态开始逐层差找找到当前子模块对应的父模块状态let parent path.slice(0, -1).reduce((memo, current){return memo[current]}, rootState)}
}接下来只需要向这个 parent 父模块的 State 状态中添加当前子模块状态即可
4问题 2如何将子模块状态挂载到父模块的状态上
子模块状态module.state;父模块状态parent;
那么直接向父模块状态中添加子模块状态就可以了吗
parent[path[path.length-1]] module.state;右侧的进度条告诉我们不会这么简单的
在 Vuex 中模块是可以动态进行添加的在 Vuex 中状态应该是响应式的
因此我们希望动态添加的模块也是响应式的数据
如果直接向对象中添加一个不存在的属性是无法被声明为响应式数据的
所以需要通过 Vue.set API 向父模块状态中添加子模块状态以此实现对象新增属性为响应式数据
这样当 Vuex 动态注册模块时新添加的状态属性就是响应式数据了
备注
如果使用 Vue.set 向一个非响应式对象添加属性相当于直接为普通对象添加属性并赋值此时即 resetStoreVM 方法执行前parent就是一个普通对象当 resetStoreVM 方法执行完成后才是响应式数据因此使用 Vue.set在两种状态下都是兼容的
5代码实现
从根模块开始递归处理将当前子模块状态定义到其对应父模块状态上
从根模块的状态开始找返回当前模块所属的父模块 parent将当前模块的 State 状态设置到父模块 parent 的 path[path.length-1] 属性中 即将所有状态都设置到 rootState 上
// src/vuex/store.js#installModuleconst installModule (store, rootState, path, module) {// 处理子模块将子模块上的状态添加到对应父模块的状态中if(path.length 0){// 从根状态开始逐层差找找到当前子模块对应的父模块状态let parent path.slice(0, -1).reduce((memo, current){return memo[current]}, rootState)// 支持 Vuex 动态添加模块将新增状态直接定义成为响应式数据Vue.set(parent, path[path.length-1], module.state);}
}6执行情况分析 首次进入 installModule 方法由于 path []不会进入状态安装逻辑此时会遍历根模块中的 actions、mutations、getters 分别放到 store 实例中的 _actions、_mutations、_wrappedGetters 中;最后通过当前模块 module.forEachChild 递归遍历子模块深度优先递归递归的终止条件是当父模块下不存在子模块时 备注在遍历处理当前模块下的子模块时完成 path 路径的拼接操作 非首次进入 installModule 方法此时 path.length 0, 进行子模块状态安装先通过 path 找到当前子模块对应的父模块状态对象并通过Vue.set向其中添加子模块状态该属性被直接定义为响应式数据
打印状态安装完成后的state此时 state 包含 Vuex 中全部模块的状态
// src/vuex/store.jsexport class Store {constructor(options) {const state options.state;// 收集所有模块中的action、mutation、getter 放到 Store 上this._actions {};this._mutations {};this._wrappedGetters {};// 1,模块收集options 格式化 - Vuex 模块树this._modules new ModuleCollection(options);console.log(格式化后的模块树对象, this._modules)// 2,模块安装installModule(this, state, [], this._modules.root);console.log(模块安装结果:state, state)}
}如上图所示根模块状态中包含模块 A 和模块 B 的状态模块 A 中包含模块 C 的状态 四结尾
本篇主要介绍了 Vuex 的 State 状态安装主要涉及以下几个点
State 状态的安装逻辑两个核心问题的思路代码实现以及执行情况分析
下一篇继续介绍 Vuex 模块相关概念Vuex 数据响应式的实现 维护日志
20211008 全篇重构调整文章目录结构添加核心逻辑分析