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.rhkb.cn/news/358028.html

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

相关文章

Java | Leetcode Java题解之第169题多数元素

题目: 题解: class Solution {public int majorityElement(int[] nums) {int count 0;Integer candidate null;for (int num : nums) {if (count 0) {candidate num;}count (num candidate) ? 1 : -1;}return candidate;} }

TLS握手中的RTT

文章目录 TLS 1.2 握手过程中的 RTT 次数TLS 1.3 1-RTT 初次TLS1.3 0-RTT 握手过程总结 TLS 1.2 握手过程中的 RTT 次数 TLS 1.2 握手通常需要2 RTT 才能完成。具体步骤如下: 第一次 RTT: 客户端发送 ClientHello:客户端生成一个随机数&…

26.3 Django路由层

1. 路由作用 在Django中, URL配置(通常称为URLconf)是定义网站结构的基础, 它充当着Django所支撑网站的目录. URLconf是一个映射表, 用于将URL模式(patterns)映射到Python的视图函数或类视图上. 这种映射机制是Django处理HTTP请求的基础, 它决定了当客户端发送请求时, Django如…

消息认证码解析

1. 什么是消息认证码 消息认证码(Message Authentication Code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。 消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥,它可以输出固定长度的数据&#x…

AIGC-Animate Anyone阿里的图像到视频 角色合成的框架-论文解读

Animate Anyone: Consistent and Controllable Image-to-Video Synthesis for Character Animation 论文:https://arxiv.org/pdf/2311.17117 网页:https://humanaigc.github.io/animate-anyone/ MOTIVATION 角色动画的目标是将静态图像转换成逼真的视频,这在在线零…

ip地址怎么写才是的对的?合法ip地址正确的格式

IP地址怎么写才是的对的?在互联网的世界里,IP地址就像是我们生活中的门牌号码,它是每个设备在网络中的唯一标识。正确的书写IP地址对于确保网络通信的顺畅至关重要。本文将带您了解合法IP地址的正确格式与书写规范,并深入探讨其在…

css如何动态累计数字?

导读:css如何动态累计数字?用于章节目录的序列数生成,用css的计数器实现起来比 js方式更简单! 伪元素 ::after ::before伪元素设置content 可以在元素的首部和尾部添加内容,我们要在元素的首部添加序列号&#xff0c…

Spring AI 介绍以及与 Spring Boot 项目整合

Spring AI 项目旨在简化使用 Spring Boot 开发包含人工智能功能的应用程序,提供抽象和支持多种模型提供商及矢量数据库提供商。 Spring AI 的功能特点 支持主流模型提供商:如 OpenAI、Microsoft、Amazon、Google 和 Huggingface 等。支持多种模型类型&a…

如何从magento1迁移到magento2

m2相较m1 变化可以说非常大,相当于从头到位都改写一遍,更现代化,更优雅。除了数据库表变化不是很大。 主要迁移的内容有: 1,主题 2,插件(自己开发的或者第三方插件) 3,数据库 主题 不能迁移到m…

STM32上实现spwm调制原理分析

在STM32微控制器上实现SPWM(正弦脉宽调制,Sinusoidal Pulse Width Modulation)调制的核心是利用高频载波(三角波)与低频基波(正弦波)作比较得出。 那么在STM32里三角波和正弦波分别是什么&…

java实现分类下拉树,点击时对应搜索---后端逻辑

一直想做分类下拉,然后选择后搜索的页面,正好做项目有了明确的需求,查找后发现el-tree的构件可满足需求,数据要求为:{ id:1, label:name, childer:[……] }形式的,于是乎,开搞! 一…

Golang | Leetcode Golang题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; const L 10 var bin map[byte]int{A: 0, C: 1, G: 2, T: 3}func findRepeatedDnaSequences(s string) (ans []string) {n : len(s)if n < L {return}x : 0for _, ch : range s[:L-1] {x x<<2 | bin[byte(ch)]}cnt : map[int]in…

文件创建与查看

touch touch命令用于创建一个新的文件。 语法&#xff1a;touch Linux路径 其中路径可以是相对路径、绝对路径或者特殊路径符都可以。 改图展示了通过 touch test.txt 命令创建了一个 test.txt文件&#xff0c;其中深色的代表文件夹&#xff0c;白色的代表文件。 使用 ls -lh…

[MYSQL] 数据库基础

1.什么是数据库 从数据库的名字可以看出,它是用来操作(增删查改....)数据的,事实上也的确如此,通过数据库,我们可以更方便.更高效的来操作.管理数据 以文件形式存储数据的缺点 文件的安全问题文件不利于数据的查询和删除文件不利于存储海量数据操作文件并不方便 为了解决上述问…

汽车IVI中控开发入门及进阶(二十九):i.MX6

前言: i.MX 6双/6Quad处理器集成多媒体应用处理器,是不断增长的多媒体产品系列的一部分,提供高性能处理,并针对最低功耗进行了优化。 i.MX 6Dual/6Quad处理器采用先进的quad-ArmCortex-A9内核,运行速度高达800 MHz,包括2D和3D图形处理器、1080p视频处理和集成电源管理。…

深入分析 Android BroadcastReceiver (六)

文章目录 深入分析 Android BroadcastReceiver (六)1. 广播机制的高级优化策略1.1 使用 Sticky Broadcast&#xff08;粘性广播&#xff09;示例&#xff1a;粘性广播&#xff08;过时&#xff0c;不推荐&#xff09; 1.2 使用 LiveData 和 ViewModel 进行组件通信示例&#xf…

潜艇伟伟迷杂交版植物大战僵尸2024最新免费安卓+ios苹果+iPad分享

嗨&#xff0c;亲爱的游戏迷们&#xff01;今天我要给你们种草一个超有趣的游戏——植物大战僵尸杂交版。这款游戏不仅继承了原有经典游戏的核心玩法&#xff0c;还加入了许多创新元素&#xff0c;让玩家能够体验到前所未有的乐趣。快来跟随我一起探索这个神奇的世界吧&#xf…

Android模拟器linux内核的下载,编译,运行,驱动开发测试

Android模拟器linux内核的下载&#xff0c;编译&#xff0c;运行&#xff0c;内核模块开发 1.下载适合Android模拟器的内核 git clone https://aosp.tuna.tsinghua.edu.cn/android/kernel/goldfish.git git branch -a git checkout android-goldfish-4.14-gchips 新建一个目录…

PriorityQueue详解(含动画演示)

目录 PriorityQueue详解1、PriorityQueue简介2、PriorityQueue继承体系3、PriorityQueue数据结构PriorityQueue类属性注释完全二叉树、大顶堆、小顶堆的概念☆PriorityQueue是如何利用数组存储小顶堆的&#xff1f;☆利用数组存储完全二叉树的好处&#xff1f; 4、PriorityQueu…

nvm安装

1、官网下载nvm压缩包 Releases coreybutler/nvm-windows (github.com)https://github.com/coreybutler/nvm-windows/releases 2、安装nvm cmd下查看nvm版本号 nvm version 3、配置镜像 在安装目录下找到settings.txt文件&#xff0c;追加淘宝镜像 node_mirror:https:/…