vuex的深入学习[基于vuex3]----篇(二)

store对象的创建

store的传递图
在这里插入图片描述

在这里插入图片描述

创建语句索引

  1. 创建vuex的语句为new Vuex.Store({…})
  2. Vuex的入口文件是index.js,store是index.js导出的store类
  3. store类是store.js文件中定义的。

Store的构造函数constructor

  1. 判断vuex是否被注入,就是将vue挂载在window对象上,自动检测window.Vue,如果有挂载,而且没有被注册过,则调用注册方法
if (!Vue && typeof window !== 'undefined' && window.Vue) {install(window.Vue)
}
  1. 断言
    断言是否被注册,是否支持promise,断言类有没有被正确的实例化,这些断言语句,在vue build出来以后,报错信息会被忽略
if (process.env.NODE_ENV !== 'production') {assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)assert(this instanceof Store, `store must be called with the new operator.`)
}
  • 支持promise语法
  • 已经执行安装函数进行装载
  • 在webpack配置的时候,npm build会将process.env.NODE_ENV 设置为true
function assert(condition, msg) {if(!condition) throw new Error(`[vuex] ${msg}`)
}
  1. 部分重要的容器
this._committing = false // 表示状态标识,在严格模式下,防止非commit操作下,state被修改
this._actions = Object.create(null) // action函数的数组的对象,保存所有action回调函数。从null中创建对象,object.create(null)没有继承任何原型方法,也就是说他的原型链没有上一层,从而定义纯粹的对象
this._actionSubscribers = [] // 订阅action操作的函数数组,里面的每个函数,将在action函数被调用之间被调用,该功能类似于插件,和主功能无关。
this._mutations = Object.create(null) // mutation函数的数组的对象,保存所有的mutations回调函数
this._wrappedGetters = Object.create(null) //保存getter函数的函数数组对象容器
this._modules = new ModuleCollection(options) // 解析并生成模块树,通过树结构,保存配置文件内容
this._modulesNamespaceMap = Object.create(null) // 保存命名空间的模块对象,以便在辅助函数createNamespacedHelpers中快速定位到待命名空间的模块。
this._subscribers = []    // 订阅mutation操作的函数数组,里面的每个函数,将在commit执行后被调用,类似于插件,和主功能无关。
this._watcherVM = new Vue() // 定义一个vue对象,vue类将在调用vuex安装函数,install 的时候,被传递进来。

简洁版

this._committing = false // 是否在进行提交状态标识
this._actions = Object.create(null) // acitons操作对象
this._mutations = Object.create(null) // mutations操作对象
this._wrappedGetters = Object.create(null) // 封装后的getters集合对象
this._modules = new ModuleCollection(options) // Vuex支持store分模块传入,存储分析后的modules
this._modulesNamespaceMap = Object.create(null) // 模块命名空间map
this._subscribers = [] // 订阅函数集合,Vuex提供了subscribe功能
this._watcherVM = new Vue() // Vue组件用于watch监视变化

ModuleCollection

this._modules = new ModuleCollection(options)

ModuleCollection函数主要是讲传入的options对象构造为一个module对象,并循环调用(this.register[key], rawModul, false)为其中的modules属性进行模块注册,使得其称为module对象后,最后options对象被构成一个完整的组件树,ModuleCollection类还提供了modules的更替功能。

constructor
export default class ModuleCollection {constructor(rawRootModule) {this.register([], rawRootModule, false)}
}
  • 形参: rawRootModule,在store中new ModuleCollection(options)传入,而options是store的构造函数参数,就是new Vuex.Store({…})传入的参数
{state, getters,actions,mutations  
}
register
register (path, rawModule, runtime = true) {if (process.env.NODE_ENV !== 'production') {assertRawModule(path, rawModule)}const newModule = new Module(rawModule, runtime)if (path.length === 0) {this.root = newModule} else {const parent = this.get(path.slice(0, -1))parent.addChild(path[path.length - 1], newModule)}if (rawModule.modules) {forEachValue(rawModule.modules, (rawChildModule, key) => {this.register(path.concat(key), rawChildModule, runtime)})}
}
参数解析
  • path是注册模块的层级关系数组,保存当前模块及各个祖先模块的名字。[a, b, c, 当前模块] => {modules: {a, modules: {b, module:{当前模块} }}}
  • rawModule是模块的配置参数,在定义模块的时候,开发者定义的模块配置内容,比如state, getter, actions等等
  • runtime标识是否是运行状态,在运行状态下,不能进行某些特定的操作。
assertRawModule
if (process.env.NODE_ENV !== 'production') {assertRawModule(path, rawModule)
}
  • 对模块的配置信息进行断言
  • 判断了getters,mtations, actions等配置的数据类型是否正确。
const newModule = new Module(rawModule, runtime),找到module.js文件找到其构造函数
  constructor (rawModule, runtime) {this.runtime = runtimethis._children = Object.create(null) // 定义子模块对象容器this._rawModule = rawModule // 保存配置参数本身const rawState = rawModule.state // 从配置参数中获得了state这个参数this.state = (typeof rawState === 'function' ? rawState() : rawState) || {} // 解析state,如果是函数,则运用工厂模式产生配置对象}
根据path模块判断当前是否为根模块
  1. 如果是根模块,则通过this.root进行保存
  2. 如果不是根模块
    • get方法传入的是路径数组,slice(0,-1)是为了去除本模块名,保留所有祖先模块的路径,从而获取夫模块。
    • get函数内部,使用了数组的reduce方法
    get (path) {return path.reduce((module, key) => {return module.getChild(key)
    }, this.root)
    }
    
      getChild (key) {return this._children[key]}addChild (key, module) {this._children[key] = module}
    
if(rawModule.modules)判断模块配置信息中,有没有子模块的配置

如果有,则递归调用注册函数register本身,传入的参数加上了子模块名的path模块层级数组,rawchildmodule是子模块配置文件,runtime是继承而来的运行标识符

获取dispatch和commit函数,并复写该函数

const store = this
const { dispatch, commit } = this
this.dispatch = function boundDispatch (type, payload) {return dispatch.call(store, type, payload)
}
this.commit = function boundCommit (type, payload, options) {return commit.call(store, type, payload, options)
}

复写的作用是将两个函数的this值绑定到vuex实例本身上,防止因为this的指向修改而被修改
这两个函数可以通过mapMutationsmapActions辅助函数转换为Vue中的普通函数,这时this指向Vue组件,而不是Vuex实例

后续代码

this.strict = strict
const state = this._modules.root.state //根据根模块的state变量索引
installModule(this, state, [], this._modules.root)//安装根模块,设置commit,dispatch函数的重载,根据是否设置命名空间,设置参数前缀,将getter,commit,action放到相对应的容器中保存起来。
resetStoreVM(this, state)// 借助vue的watch功能和computed功能,实现数据的响应式
plugins.forEach(plugin => plugin(this)) // 插件的注册,和主功能无关
const useDevtools = options.devtools !== undefined ? options.devtools : Vue.config.devtools
if (useDevtools) { // vue调试工具的处理devtoolPlugin(this)
}
installModule(模块安装函数)
参数介绍
  • store: store对象实例,new Vuex.store({…})生成的对象
  • rootState: 根模块的state对象
  • path: 当前模块所处的层级数组
  • module: 模块对象
  • hot
实例代码
  function installModule (store, rootState, path, module, hot) {const isRoot = !path.length // 判断当前模块是否为根模块const namespace = store._modules.getNamespace(path) //  获取模块的命名空间if (module.namespaced) {store._modulesNamespaceMap[namespace] = module}if (!isRoot && !hot) {const parentState = getNestedState(rootState, path.slice(0, -1))const moduleName = path[path.length - 1]store._withCommit(() => {Vue.set(parentState, moduleName, module.state)})}
}

补充
getNamespace

//从跟模块中出发,根据给出的路径数组,递归每一个层级的模块
getNamespace(path) {let module = this.rootreturn path.reduce((namespace, key) => {module = module.getChild(key)return namespace + (module.namespaced ? key + "/" : '')}, '')
}
{moduleA:{namespaced:true,modules:{moduleB:{namespaced:false,modules:{moduleC:{namespaced:true,}}}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/32866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法】二叉树 - 理论基础

1.种类 1.1 满二叉树 只有度为0和2的节点,且度为0的节点都都在同一层。深度为k,有2^k-1个节点。 1.2 完全二叉树 在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都…

常说的云VR是什么意思?与传统vr的区别

虚拟现实(Virtual Reality,简称VR)是一种利用计算机技术模拟产生一个三维空间的虚拟世界,让用户通过视觉、听觉、触觉等感官,获得与现实世界类似或超越的体验。VR技术发展历程可追溯至上世纪,经历概念提出、…

某大厂程序员吐槽:离职交接时,新人被工作量吓退,领导却污蔑我故意劝退新人,我怒晒工作短信反击证明,新人看了后也决定走人了!

一位知名大公司的程序员分享了他离职时的遭遇:在交接工作时,新进的同事因工作量过大而感到压力,但出乎意料的是,他们的领导却指责我故意吓唬新人。为了证明自己的清白,我晒出了工作短信作为反击,结果连新人…

Linux系统编程--软/硬连接

真正找到磁盘上文件的并不是文件名,而是inode。 其实在linux中可以让多个文件名对应于同一个inode。 命令: 软连接:ln -s 原文件名 新文件名 硬链接:ln 原文件名 新文件名 删除链接文件:unlink 文件名执行上面两条命令…

matplotlib之常见图像种类

Matplotlib 是一个用于绘制图表和数据可视化的 Python 库。它支持多种不同类型的图形,以满足各种数据可视化需求。以下是一些 Matplotlib 支持的主要图形种类: 折线图(Line Plot): 用于显示数据随时间或其他连续变量的…

Git使用过程中涉及的几个区域

一. 简介 Git 是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理,也是 Linus Torvalds 为了帮助管理 Linux内核开发而开发的一个开放源码的版本控制软件。 本文简单了解一下 git涉及的几个部分,以及git 常…

vue登陆密码加密,java后端解密

前端 安装crypto-js npm install crypto-js加密 //引入crypto-js import CryptoJS from crypto-js;/** ---密码加密 start--- */ const SECRET_KEY CryptoJS.enc.Utf8.parse("a15q8f6s5s1a2v3s"); const SECRET_IV CryptoJS.enc.Utf8.parse("a3c6g5h4v9sss…

基于网络搜索的长篇问答能力优化:FoRAG

检索增强生成(RAG,Retrieval Augmented Generation)可以利用搜索引擎检索技术来提升长篇问答质量,因而在 QA 任务中广受欢迎。尽管有多种开源方法和网络增强的商业系统如 Bing Chat 出现,但生成长篇答案的事实性和逻辑…

ruoyi添加自己的菜单

先把自己自定义的view填写好 在菜单管理模块 因为我已经新增过,所以就看看我填的啥就行了 我发现一个问题,路由地址可以填index2或者scooldemo/index2都可以(这个包含了文件夹路径),反正组件路径一定要填对就可以了。 …

【UML用户指南】-21-对基本行为建模-活动图

目录 1、概念 2、组成结构 2.1、动作 2.2、活动节点 2.3、控制流 2.4、分支 2.5、分岔和汇合 2.6、泳道 2.7、对象流 2.8、扩展区域 3、一般用法 3.1、对工作流建模 3.2、对操作建模 一个活动图从本质上说是一个流程图,展现从活动到活动的控制流 活动图…

MySQL命名规范(自用)

MtySQL命名规范 基本通用规范 1.【推荐】关键字必须大写 所有关键字必须大写,如:INSERT、UPDATE、DELETE、SELECT及其子句,IF……ELSE、CASE、DECLARE等 2.【强制】字段和建表必须写备注 COMMENT写备注 3.【强制】字母数字下划线 采用26个英…

国产MCU芯片(2):东软MCU概览及触控MCU

前言: 国产芯片替代的一个主战场之一就是mcu,可以说很多国内芯片设计公司都打算或者已经在设计甚至有了一款或多款的量产产品了,这也是国际大背景决定的。过去的家电市场、过去的汽车电子市场,的确国产芯片的身影不是很常见,如今不同了,很多fabless投身这个行业,一种是…

OpenGL3.3_C++_Windows(18)

接口块: glsl彼此传输数据,通过in / out,当更多的变量,涉及数组和结构体接口块(Interface Block)类似struct,in / out 块名{……}实例名 Uniform缓冲对象: 首先理解uniform Object:负责向gl…

程序人生:关于RHCE红帽认证这件事

花了两个月备考红帽,最终终于双满分通过。 关于考试 RHCE红帽认证总共需要考两门:RHCSA、RHCE。 RHCSA主要是考察基本的Linux操作:用户、权限、空间扩容、yum、容器等内容。 RHCE主要是考察ansible playbook 代码的开发。 通过考试没有别…

【内存管理】页面分配机制

前言 Linux内核中是如何分配出页面的,如果我们站在CPU的角度去看这个问题,CPU能分配出来的页面是以物理页面为单位的。也就是我们计算机中常讲的分页机制。本文就看下Linux内核是如何管理,释放和分配这些物理页面的。 伙伴算法 伙伴系统的…

设计模式4-模版方法

设计模式 重构获得模式重构的关键技法1. 静态转动态2. 早绑定转晚绑定3. 继承转组合4. 编译时依赖转运行时依赖5. 紧耦合转松耦合 组件协助动机模式定义结构 要点总结。 例子示例解释: 重构获得模式 设计模式的目的是应对变化,提高复用 设计模式的要点…

[SAP ABAP] 排序内表数据

语法格式 整表排序 SORT <itab> [ASCENDING|DESCENDING]. 按指定字段排序 SORT <itab> BY f1 [ASCENDING|DESCENDING] f2 [ASCENDING|DESCENDING] ... fn [ASCENDING|DESCENDING].<itab>&#xff1a;代表内表 不指定排序方式则默认升序排序 示例1 结果显…

.hmallox勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 在当今数字化时代&#xff0c;勒索病毒已经成为网络安全的一大威胁&#xff0c;其中包括了最近出现的.hmallox勒索病毒。这类恶意软件不仅能够对计算机系统进行加密&#xff0c;还会要求用户支付赎金以换取解密密钥&#xff0c;给个人用户和企业带来了严重的…

C++的特殊类设计 饥饿汉模式

目录 特殊类设计 设计一个不能被拷贝的类 设计一个只能在堆上创建对象的类 设计一个只能在栈上创建对象的类 设计一个不能继承的类 设计模式 单例模式 饿汉模式 饥汉模式 特殊类设计 设计一个不能被拷贝的类 C98的设计方式&#xff1a;将该类的拷贝构造和赋值运算符…

一小时搞定Git(含盖IDEA使用)

文章目录 1. git基本概念1.1版本控制1.1.1 版本控制软件 2. 命令的使用2.1 Linux命令2.2 git基础指令2.2.1 设置用户2.2.2 初始化本地仓库2.2.3 查看本地仓库状态2.2.4 添加暂存区域2.2.5 提交本地库2.2.6 切换版本 2.3 分支操作2.3.1 分支基本操作2.3.2 合并操作2.3.4 分支开发…