【Vuex状态管理】Vuex的基本使用;核心概念State、Getters、Mutations、Actions、Modules的基本使用
目录
- 1_应用状态管理
- 1.1_状态管理
- 1.2_复杂的状态管理
- 1.3_Vuex的状态管理
- 2_Vuex的基本使用
- 2.1_安装
- 2.2_创建Store
- 2.3_组件中使用store
- 3_核心概念State
- 3.1_单一状态树
- 3.2_组件获取状态
- 3.3_在setup中使用mapState
- 4_核心概念Getters
- 4.1_getters的基本使用
- 4.2_getters第二个参数
- 4.3_getters的返回函数
- 4.4_mapGetters的辅助函数
- 5_核心概念Mutations
- 5.1_使用
- 5.2_Mutation常量类型
- 5.3_mutation重要原则
- 6_核心概念Actions
- 6.1_基本使用
- 6.2_分发操作
- 6.3_actions的异步操作
- 7_核心概念Modules
- 7.1_module的基本使用
- 7.2_module的局部状态
- 7.3_module的命名空间
- 7.4_module修改或派发根组件
1_应用状态管理
1.1_状态管理
在开发中,应用程序需要处理各种各样的数据,这些数据需要保存在应用程序中的某一个位置,对于这些数据的管理就称之为是 状态管理。
在前面是如何管理自己的状态呢?
- 在Vue开发中,使用组件化的开发方式;
- 而在组件中定义data或者在setup中返回使用的数据,这些数据称之为state;
- 在模块template中可以使用这些数据,模块最终会被渲染成DOM,称之为View;
- 在模块中会产生一些行为事件,处理这些行为事件时,有可能会修改state,这些行为事件称之为actions;
1.2_复杂的状态管理
JavaScript开发的应用程序,已经变得越来越复杂了:
- JavaScript需要管理的状态越来越多,越来越复杂;
- 这些状态包括服务器返回的数据、缓存数据、用户操作产生的数据等等;
- 也包括一些UI的状态,比如某些元素是否被选中,是否显示加载动效,当前分页;
当的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态;
- 来自不同视图的行为需要变更同一状态;
是否可以通过组件数据的传递来完成呢?
- 对于一些简单的状态,确实可以通过props的传递或者Provide的方式来共享状态;
- 但是对于复杂的状态管理来说,显然单纯通过传递和共享的方式是不足以解决问题的,比如兄弟组件如何共享数据呢
1.3_Vuex的状态管理
管理不断变化的state本身是非常困难的:
- 状态之间相互会存在依赖,一个状态的变化会引起另一个状态的变化,View页面也有可能会引起状态的变化;
- 当应用程序复杂时,state在什么时候,因为什么原因而发生了变化,发生了怎么样的变化,会变得非常难以控制和追踪;
因此,是否可以考虑将组件的内部状态抽离出来,以一个全局单例的方式来管理呢?
- 在这种模式下,组件树构成了一个巨大的 “试图View”;
- 不管在树的哪个位置,任何组件都能获取状态或者触发行为;
- 通过定义和隔离状态管理中的各个概念,并通过强制性的规则来维护视图和状态间的独立性,的代码边会变得更加结构化和易于维护、跟踪;
这就是Vuex背后的基本思想,它借鉴了Flux、Redux、Elm(纯函数语言,redux有借鉴它的思想);
Vue官方也在推荐使用Pinia进行状态管理,后续学习
参考官网的图

2_Vuex的基本使用
2.1_安装
npm install
2.2_创建Store
每一个Vuex应用的核心就是store(仓库): store本质上是一个容器,它包含着应用中大部分的状态(state);
Vuex和单纯的全局对象有什么区别?
-
第一:Vuex的状态存储是响应式的。 当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会被更新;
-
第二:不能直接改变store中的状态。
- 改变store中的状态的唯一途径就显示提交 (commit) mutation;
- 这样使得可以方便的跟踪每一个状态的变化,从而让能够通过一些工具帮助更好的管理应用的状态;
demo:
(1)在src文件夹下,建立一个新文件夹store,在该文件夹下,一般创建index.js文件,也可根据实际开发创建。
src/store/index.js
import { createStore } from 'vuex'const store = createStore({state: () => ({counter: 100})
})
(2)在main.js注册
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'createApp(App).use(store).mount('#app')
(3)在App.vue中调用
<template><div class="app"><!-- store中的counter --><h2>App当前计数: {{ $store.state.counter }}</h2></div>
</template>
2.3_组件中使用store
在组件中使用store,按照如下的方式:
- 在模板tempte中使用,比如2.2的demo
- 在options api中使用,比如computed;
- 在setup中使用;
<template><div class="app"><!-- 在模板tempte中使用store --><h2>Home当前计数: {{ $store.state.counter }}</h2><h2>Computed当前计数: {{ storeCounter }}</h2><h2>Setup当前计数: {{ counter }}</h2><button @click="increment">+1</button></div>
</template><script>export default {//在options api中使用,比如computed;computed: {storeCounter() {return this.$store.state.counter}}}
</script><!-- 在setup中使用store -->
<script setup>import { toRefs } from 'vue'import { useStore } from 'vuex'const store = useStore()const { counter } = toRefs(store.state)function increment() {store.commit("increment")}
</script>
3_核心概念State
3.1_单一状态树
Vuex 使用单一状态树:
- 用一个对象就包含了全部的应用层级的状态;
- 采用的是SSOT,Single Source of Truth,也可以翻译成单一数据源;
这也意味着,每个应用将仅仅包含一个 store 实例, 单状态树和模块化并不冲突,后面会涉及到module的概念;
单一状态树的优势:
- 如果状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难;
- 所以Vuex也使用了单一状态树来管理应用层级的全部状态;
- 单一状态树能够让最直接的方式找到某个状态的片段;
- 而且在之后的维护和调试过程中,也可以非常方便的管理和维护;
3.2_组件获取状态
在前面的demo已知如何在组件中获取状态了。
当然,如果觉得那种方式有点繁琐(表达式过长),可以使用计算属性:
computed: {storeCounter() {return this.$store.state.counter}}
但是,如果有很多个状态都需要获取话,可以使用mapState的辅助函数:
- mapState的方式一:对象类型;
- mapState的方式二:数组类型;
- 也可以使用展开运算符和来原有的computed混合在一起;
3.3_在setup中使用mapState
在setup中如果单个获取状态是非常简单的, 通过useStore拿到store后去获取某个状态即可。
但是如果使用 mapState 如何获取状态?
(1) 默认情况下,Vuex并没有提供非常方便的使用mapState的方式,下面这种方式不建议使用
<template><div class="app"><!-- 在模板中直接使用多个状态 --><h2>name: {{ $store.state.name }}</h2><h2>level: {{ $store.state.level }}</h2><h2>avatar: {{ $store.state.avatarURL }}</h2></div>
</template><script setup>import { computed } from 'vue'import { mapState, useStore } from 'vuex'// 一步步完成,步骤繁琐const { name, level } = mapState(["name", "level"])const store = useStore()const cName = computed(name.bind({ $store: store }))const cLevel = computed(level.bind({ $store: store }))
</script>
(2)这里进行了一个函数的封装,简化步骤
src/hooks/useState.js
import { computed } from 'vue'
import { useStore, mapState } from 'vuex'export default function useState(mapper) {const store = useStore()const stateFnsObj = mapState(mapper)const newState = {}Object.keys(stateFnsObj).forEach(key => {newState[key] = computed(stateFnsObj[key].bind({ $store: store }))})return newState
}
使用该函数
<template><div class="app"><!-- 在模板中直接使用多个状态 --><h2>name: {{ $store.state.name }}</h2><h2>level: {{ $store.state.level }}</h2><h2>avatar: {{ $store.state.avatarURL }}</h2></div>
</template><script setup>import useState from "../hooks/useState"// 使用useState封装函数const { name, level } = useState(["name", "level"])
</script>
(3)更推荐下面的使用方式
<template><div class="app"><!-- 在模板中直接使用多个状态 --><h2>name: {{ $store.state.name }}</h2><h2>level: {{ $store.state.level }}</h2><h2>avatar: {{ $store.state.avatarURL }}</h2></div>
</template><script setup>import { computed, toRefs } from 'vue'import { mapState, useStore } from 'vuex'// 3.直接对store.state进行解构(推荐)const store = useStore()const { name, level } = toRefs(store.state)
</script>
4_核心概念Getters
4.1_getters的基本使用
某些属性可能需要经过变化后来使用,这个时候可以使用getters

4.2_getters第二个参数
getters可以接收第二个参数
getters: {// 2.在该getters属性中, 获取其他的gettersmessage(state, getters) {return `name:${state.name} level:${state.level} friendTotalAge:${getters.totalAge}`}}
4.3_getters的返回函数
getters: {// 3.getters是可以返回一个函数的, 调用这个函数可以传入参数(了解)getFriendById(state) {return function(id) {const friend = state.friends.find(item => item.id === id)return friend}}}
4.4_mapGetters的辅助函数
可以使用mapGetters的辅助函数
<template><div class="app"><h2>doubleCounter: {{ doubleCounter }}</h2><h2>friendsTotalAge: {{ totalAge }}</h2><!-- 根据id获取某一个朋友的信息 --><h2>id-111的朋友信息: {{ getFriendById(111) }}</h2><h2>id-112的朋友信息: {{ getFriendById(112) }}</h2></div>
</template><script>import { mapGetters } from 'vuex'export default {computed: {...mapGetters(["doubleCounter", "totalAge"]),...mapGetters(["getFriendById"])}}
</script>
也可在setup中使用
<template><div class="app"><h2>message: {{ message }}</h2></div>
</template><script setup>import { computed, toRefs } from 'vue';import { mapGetters, useStore } from 'vuex'const store = useStore()// 1.使用mapGetters ,较麻烦// const { message: messageFn } = mapGetters(["message"])// const message = computed(messageFn.bind({ $store: store }))// 2.直接解构, 并且包裹成ref// const { message } = toRefs(store.getters)// 3.针对某一个getters属性使用computedconst message = computed(() => store.getters.message)
</script>
5_核心概念Mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
5.1_使用
在提交mutation的时候,会携带一些数据,这时可以使用参数,注意payload为对象类型
mutation :{add(state,payload){statte.counter + = payload}
}
提交
$store.commit({type: "add",count: 100
})
5.2_Mutation常量类型
demo:
(1)在mutaition-type.js,定义常量
export const CHANGE_INFO = "changeInfo"
(2)在store使用常量
mutations: {[CHANGE_INFO](state, newInfo) {state.level = newInfo.levelstate.name = newInfo.name}}
(3)在使用的

5.3_mutation重要原则
一条重要的原则就是,mutation 必须是同步函数
- 这是因为devtool工具会记录mutation的日记;
- 每一条mutation被记录,devtools都需要捕捉到前一状态和后一状态的快照;
- 但是在mutation中执行异步操作,就无法追踪到数据的变化;
6_核心概念Actions
6.1_基本使用
Action类似于mutation,不同在于:
-
Action提交的是mutation,而不是直接变更状态;
-
Action可以包含任意异步操作;
有一个非常重要的参数context:
- context是一个和store实例均有相同方法和属性的context对象;
- 所以可以从其中获取到commit方法来提交一个mutation,或者通过 context.state 和 context.getters 来获取 state 和getters;
具体案例参考这篇文章 :https://blog.csdn.net/qq_21980517/article/details/103398686
6.2_分发操作

6.3_actions的异步操作
Action 通常是异步的,可以通过让action返回Promise,知道 action 什么时候结束,然后,在Promise的then中来处理完成后的操作。
demo:
index.js中,以发送网络请求为例
action{fetchHomeMultidataAction(context) {// 1.返回Promise, 给Promise设置then// fetch("http://123.207.32.32:8000/home/multidata").then(res => {// res.json().then(data => {// console.log(data)// })// })// 2.Promise链式调用// fetch("http://123.207.32.32:8000/home/multidata").then(res => {// return res.json()// }).then(data => {// console.log(data)// })return new Promise(async (resolve, reject) => {// 3.await/asyncconst res = await fetch("http://123.207.32.32:8000/home/multidata")const data = await res.json()// 修改state数据context.commit("changeBanners", data.data.banner.list)context.commit("changeRecommends", data.data.recommend.list)resolve("aaaaa")})}}
test3.vue中
<script setup>import { useStore } from 'vuex'// 告诉Vuex发起网络请求const store = useStore()store.dispatch("fetchHomeMultidataAction").then(res => {console.log("home中的then被回调:", res)})</script>
7_核心概念Modules
7.1_module的基本使用
Module的理解?
- 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂时,store 对象就有可能变得相当臃肿;
- 为了解决以上问题,Vuex 允许将 store 分割成模块(module);
- 每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

7.2_module的局部状态
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象

7.3_module的命名空间
默认情况下,模块内部的action和mutation仍然是注册在全局的命名空间中的:
- 这样使得多个模块能够对同一个 action 或 mutation 作出响应;
- Getter 同样也默认注册在全局命名空间;
如果希望模块具有更高的封装度和复用性,可以添加 namespaced: true 的方式使其成为带命名空间的模块, 当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
demo:counter,js
const counter = {namespaced: true, //命令空间state: () => ({count: 99}),mutations: {incrementCount(state) {console.log(state)state.count++}},getters: {doubleCount(state, getters, rootState) {return state.count + rootState.rootCounter}},actions: {incrementCountAction(context) {context.commit("incrementCount")}}
}export default counter
7.4_module修改或派发根组件
在action中修改root中的state,那么有如下的方式

相关文章:
【Vuex状态管理】Vuex的基本使用;核心概念State、Getters、Mutations、Actions、Modules的基本使用
目录 1_应用状态管理1.1_状态管理1.2_复杂的状态管理1.3_Vuex的状态管理 2_Vuex的基本使用2.1_安装2.2_创建Store2.3_组件中使用store 3_核心概念State3.1_单一状态树3.2_组件获取状态3.3_在setup中使用mapState 4_核心概念Getters4.1_getters的基本使用4.2_getters第二个参数4…...
Linux centos7 bash编程(循环与条件判断)
在编程训练中,循环结构与条件判断十分重要。 根据条件为真为假确定是否执行循环。 有时,根据条件的真假结果,决定执行哪些语句,这就是分支语句。 为了训练分支语句与循环语句,我们设计一个案例: 求一组…...
设计模式-6--装饰者模式(Decorator Pattern)
一、什么是装饰者模式(Decorator Pattern) 装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你在不修改现有对象的情况下,动态地将新功能附加到对象上。这种模式通过创建一个包装类,…...
质量属性案例-架构真题(二十一)
试题一 某电子商务公司升级会员与促销管理系统,向用户提交个性化服务,提高用户粘性。在项目建立之初,公司领导人一致认为目标是提升会员管理方式的灵活性,由于当前用户规模不大,用户简单,系统方面不需要做…...
nacos Error to process server push response
nacos2.0.3报错: Error to process server push response 解决办法: 排查项目当中有没有直接或间接依赖reflections: <dependency><groupId>org.reflections</groupId><artifactId>reflections</artifactId>…...
神经网络NLP基础 循环神经网络 LSTM
用的时候,只关心token的输入,以及hidden state就好了 sequence的length是多少,lstm的cell的数量就是多少 LSTM BI-LSTM stacked lstm GRU 实现...
Oracle数据传输加密方法
服务器端“dbhome_1\NETWORK\ADMIN\”sqlnet.ora文件中添加 SQLNET.ENCRYPTION_SERVER requested SQLNET.ENCRYPTION_TYPES_SERVER (RC4_256) 添加后新的链接即刻生效,服务器无需重新启动。 也可以通过Net manager管理工具添加 各个参数含义如下: 是…...
Android列表片段
下面创建第二个片段WorkoutFragment,它包含不同训练项目构成的一个列表,用户可以从这个列表中选择训练项目。 列表视图是只包含一个列表的片段 列表片段是一种专门处理列表的片段,它会自动绑定到一个列表视图,所以不需要另外创建…...
【元宇宙】智能手机万岁
凭借出色的新设备,我们很快就能进人元字宙,想象这样的情景是很趣的。但是,至少到21世纪20年代,元宇宙时代的大多数设备很可能是我们已经在使用的设备。 AR 和 VR 设备不仅面临重大的技术、财务和体验障碍,而且它们在上…...
华为mate60的发布代表着什么?有什么意义?
华为Mate60的发布代表着华为在技术领域的持续突破和创新。该产品预计将引入更强大的处理器、更高分辨率的屏幕、更强大的摄像头等前沿技术,进一步巩固华为在技术领域的领先地位。 此外,华为Mate60的发布还具有重塑品牌形象的意义。在美国制裁下ÿ…...
huggingface下载模型文件(基础入门版)
huggingface是一个网站,类似于github,上面拥有众多开源的模型、数据集等资料,人工智能爱好者可以很方便的上面获取需要的数据,也可以上传训练好的模型,制作的数据集等。本文只介绍下载模型的方法,适合新手入…...
在JS中tramsform与translate区别
在JavaScript中,"transform"和"translate"是用于处理HTML元素的样式属性,它们有以下区别: transform属性: transform属性是一个通用的属性,用于应用一系列的变换效果,包括平移、旋转、…...
ebay测评,物理环境与IP环境:解决平台风控问题的关键
近期eBay平台出现了大量风控问题,导致许多买家账号受到影响。实际上,这主要是由于环境搭建方面存在主要问题。时至2023年,许多人的技术方案仍停留在几年前,要么使用一键新机工具配合国外IP,要么使用指纹浏览器配合国外…...
05-Redis
1、Redis为什么快? 1、纯内存操作 2、单线程可以省去多线程时CPU上下文会切换的时间 3、渐进式ReHash、缓存时间戳 数组需要扩容的时候,他会维护两张hash表,比如第一张的数组长度为6,另一张的数组长度为12,在set和g…...
MSST-NET:用于高光谱和多光谱图像融合的多尺度空间-光谱Transfomer网络
1.网络结构 主要贡献: 提出了一种多尺度空间光谱Transformer网络光谱多头注意力旨在提取光谱特征引入多尺度波段/补丁嵌入来提取多尺度特征自监督训练 痛点:卷积核的感受野有限,基于卷积神经网络CNN的融合方法无法利用特征图中的全局关系…...
代码随想录笔记--二叉树篇
1--递归遍历 1-1--前序遍历 前序遍历:根→左→右; #include <iostream> #include <vector>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode() : val(0), left(nullptr), right(nullptr) {}TreeNode(int x) : val(x), le…...
JavaScript中包含对象的数组去重
一.数组遍历 function Uniarray(array) {// 接收去重后的数组let resArr [];// 遍历数组for (let i 0; i < array.length; i) {let isFind false;// 检查当前元素是否已存在于结果数组中for (let j 0; j < resArr.length; j) {// 使用严格相等运算符(&am…...
gRPC-GateWay Swagger 实战
上一次我们分享了关于 gRPC-Gateway 快速实战 ,可以查看地址来进行回顾 : 也可以查看关于 gRPC 的历史文章: gRPC介绍 gRPC 客户端调用服务端需要连接池吗? gRPC的拦截器 gRPC的认证 分享一下 gRPC- HTTP网关 I 今天主要是分享关于 gRPC-G…...
【webpack】HMR热更新原理
本文:参考文章 一、HMR是什么,为什么出现 1、出现的原因 之前,应用的加载、更新都是一个页面级别的操作,即使单个代码文件更新,整个页面都要刷新,才能拿到最新的代码同步到浏览器,导致会丢失…...
Ceph构件及组件分析
Ceph存储架构 Ceph 存储集群由几个不同的daemon组成,每个daemon负责Ceph 的一个独特功能并。每个守护进程是彼此独立的。 下面将简要介绍每个Ceph组件的功能: RADOS(Reliable Autonomic Distributed Object Store, RADOS) RADOS…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
