Vuex 深入浅出超详细
什么是Vuex🤔❓
Vuex 官网🔗: Vuex 是一个专为 Vue.js 应用程序设计的
状态管理库
,它提供了一种
集中式管理
应用中的状态;
状态管理模式: 它让组件的
状态(数据)
,管理变得集中、有序,便于在整个应用中,共享和维护数据;
集中式存储: 它将应用的所有组件
状态(数据)
,集中到一个单一的存储对象中,使得统一管理;
这是什么意思呢🤔❓
在复杂的Vue应用中: 多个组件常常需要共享
状态(数据)
,直接传递props、使用事件机制会使程序变得 复杂且难以维护;
Vuex 是一个插件,可以帮我们管理 vue 通用的数据实现:多组件数据共享,多组件共同修改数据信息;
Vuex 应用场景:****跨组件共享状态 比如用户信息、购物车内容等,Vuex 提供了一个中心化的存储,
使得这些数据可以在任何组件中访问和更新,而无需通过复杂的父子组件传递或事件监听;
(官方)注意: 不是所有的场景都适用于
Vuex
,只有在必要的时候才使用
Vuex
使用了Vuex之后,会附加更多的框架中的概念进来,增加了项目的复杂度,(数据的操作更便捷,数据的流动更清晰)
创建\使用:Vuex
自定义创建项目:
vue create vuex-demo
勾选:css预处理器、正常情况还需要勾选
vuex
,
router
此处演示个人搭建环境;
安装Vuex 创建仓库:
vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装,注意版本兼容:vue2\3\3原则;
yarnadd vuex@3 #或 npm i vuex@3
创建仓库 store/index.js
为了维护项目目录的整洁,在src目录下新建一个
store
目录其下放置一个
index.js
📄
Vuex的store是一个集中存储应用所有组件共享状态的地方,所有,共享的数据都要统一放到 Store 中的 State 中存储;
它类似于一个全局数据仓库,在组件中访问状态: 通过
this.$store
访问
store
中的数据、触发
mutations
、调用
actions
等
// 导入 vue、vueximport Vue from'vue'import Vuex from'vuex'// 启用 Vuex 插件
Vue.use(Vuex)// 创建仓库 store 状态,即数据: // 类似于vue组件中的data、data 是组件自己的数据;// state 中的数据整个vue项目的组件都能访问到;const store =newVuex.Store({state:{count:100}})// 导出仓库 storeexportdefault store
导入main 挂载Vue实例
在Vue应用中引入Store:
main.js
中导入store,并将其添加到Vue实例中作为选项;
import Vue from'vue'import App from'./App.vue'import store from'./store'
Vue.config.productionTip =falsenewVue({//挂载至Vue实例render:h=>h(App),
store
}).$mount('#app')
在组件中访问状态数据
App.js: 通过
this.$store
访问
store
中的数据,此数据可以在任何组件中进行访问;
<template><divid="app"><p>store公共仓库获取数据: {{ $store.state.count }}</p></div></template><script>exportdefault{name:'App',}</script><style></style>
state状态:
**在Vuex中,State是状态管理的核心组成部分之一,它扮演着应用
单一数据源
的角色:**
单一数据源:
State
是
Vuex store
中存储的所有组件共享的数据状态,
官方定义: 将数据称为 State状态;
它提供了一个全局的、集中式的存储空间,使得任何组件都能访问到这些状态,从而实现状态的统一管理;
响应式:Vue的响应式系统使得当
state
中的数据发生变化时,所有依赖于这些数据的Vue组件能够自动更新;
这意味着你可以在组件中直接使用store中的状态,并且当状态改变时,视图会自动响应这些变化;
多组件使用Vuex:
案例: 在
App.JS
主组件中引入,多个组件同时获取:
Vuex
的数据进行展示; Son1.vue\Son2.vue
<template><divclass="box"><h2>Son1 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label></div></template><script></script><style></style>
获取Vuex数据: 通过
$store
访问的语法,可以直接在
组件
、
组件脚本.JS
、
src/main.JS
快速访问;
//Vue模板中直接使用{{ $store.state.xxx }}//Vue模板.js文件中获取this.$store.state.xxx
//src/main.JS 主文件中获取import store from'./store'
store.state.xxx;
辅助函数 mapState
mapState辅助函数:为了简化组件中对
state
的访问,
Vuex
提供了
mapState辅助函数
,可以将
store
中的状态映射为组件的计算属性;
正常情况下,我们在组件中访问数据通过:
{{ $store.state.xxx }}
、
this.$store.state.xxx
、
...
**实际使用过程有点麻烦,mapState函数,可以直接将
state-store状态数据
映射为一个计算属性直接访问:**
{{ xxx }}
- mapState函数:
mapState(['xxx','xxx']);
可以获取对应store状态数据
,赋值给 计算属性,方便快速访问;
<template><divid="app"><h1>
根组件
- {{ title }}
<!-- - {{ $store.state.title }} --></h1><p>store公共仓库获取数据: {{ count }}</p><!-- {{ $store.state.count }} --><hr><Son1></Son1><Son2></Son2></div></template><script>import Son1 from'./components/Son1.vue';import Son2 from'./components/Son2.vue';import{ mapState }from'vuex';//通过ES6 语法对象解构直接获取mapState;exportdefault{name:'App',components:{ Son1, Son2,},created(){//created初始化钩子函数\查看$store\mapState对象属性;
console.log("组件脚本中访问Vuex: "+this.$store.state.title);
console.log("mapState['title']: "+mapState(['title']));
console.log("mapState 对象属性: "+mapState);},//计算属性computed:{...mapState(['title','count']),//通过ES6 语法对象展开运算符,导出的状态映射给计算属性;//如果没有 ...mapState(['title','count']), 为了方便页面获取 $store.state 状态数据,通常需要自定义函数;diytitle(){returnthis.$store.state.title;}//方便组件使用,$store.state 状态数据,当然计算函数支持更多自定义操作;}}</script><style></style>
使用State的注意事项
禁止直接修改:
直接修改
store
中的
state状态数据
是被严格禁止的,
任何状态的改变都必须通过提交
mutation
来完成,以确保状态变更的可追踪性和一致性;
模块化状态: 在大型应用中,状态可能会非常复杂,因此可以将
state
分割到不同的模块中,
每个模块拥有自己的
state
,这有助于管理复杂的状态结构,后面介绍:Vuex模块化
状态修改mutations
**在Vuex中,
mutations
是用于改变状态唯一合法方式,它遵循严格同步规则,确保状态变更的可预测性和调试的便利性**
Vuex 遵循单向数据流,组件中不能直接修改仓库的数据:
但, 默认情况下并不会报错;
👇👇
<!-- Vuex store、state状态数据可以直接修改 --><template><divclass="box"><h2>Son1 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><button@click="$store.state.count++">值 + 1</button><!-- 错误写法但不会报错; --><button@click="addcount2()">值 + 2</button><!-- 错误写法但不会报错; --></div></template><script>exportdefault{//直接修改Vuex store、state状态数据methods:{addcount2(){this.$store.state.count+=2;}}}</script>
Vuex 严格模式:
Vuex 的严格模式是一种开发时的辅助工具,它强制所有的状态变更必须通过 mutation 来进行:
这有助于维护状态的一致性,避免了状态的隐式修改,使得应用的行为更加可预测;
启用方式:在创建
Vuex store
实例时,通过设置
strict: true
启用严格模式:
const store =newVuex.Store({strict:true// ...store配置});
mutatios 修改状态:
为什么可以直接修改,还要使用mutations:
Mutations是Vuex中实现状态变更的核心机制,它确保了状态的改变是有序的、可追踪的,并且遵循一定的规范:
- 单一职责:将状态变更逻辑封装在
mutations
中,使得这部分代码更加模块化和易于测试; - 可追踪性:通过集中管理状态变更,使得开发者可以更容易地跟踪应用状态的变化历史;特别是在使用
Vue DevTools
时,可以清晰地看到每次mutation
对状态的影响;
使用:mutatios 修改state状态:
- 在Vuex实例mutatios中定义=>处理函数: 这些函数必须是同步的,以确保状态变更的清晰和可追踪;每一个处理函数对应一个状态数据,它接收两个参数:
state(必须、状态数据)
、payload(可选、传递参数)
- 在需要操作state状态数据,调用对应mutation处理并提交:
this.$store.commit('处理函数名', 传递参数);
定义 mutations 事件函数
**在Vuex的
store
配置中,定义
mutations
对象,其中:**
键 =是=>事件类型(通常是大写命名)
、
值=是=>处理函数
// 创建仓库 store 状态,即数据: // 类似于vue组件中的data、data 是组件自己的数据;// state 中的数据整个vue项目的组件都能访问到;const store =newVuex.Store({//开启严格模式strict:true,state:{count:10,title:"大标题1",},//mutations对象其中键是事件类型通常是大写命名)、值是处理函数;mutations:{//state: 表示当前Vuex中的state状态数据库,用来获取其操作数据;ADD_COUNT(state){ state.count++;},//带参传递数据: 参数只能一个,如果有多个参数,包装成一个{对象}\[数组] 传递; ADD_COUNTX(state,payload){ state.count+=payload }}})
使用 mutations 事件函数
在组件中通过,调用、提交:mutation处理函数,形式完成,状态修改:
Son2.vue
<template><divclass="box"><h2>Son2 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><button@click="addCount()">值 + 1</button><!-- mutatios修改state --><button@click="addCountx(3)">值 + 3</button><!-- mutatios带 参? 修改state --><button@click="addCountx(5)">值 + 5</button><!-- mutatios带 参? 修改state --></div></template><script>exportdefault{methods:{//无参自动+1addCount(){this.$store.commit('ADD_COUNT');},addCountx(x){this.$store.commit('ADD_COUNTX',x);}//自定义传参添加数值;}}</script>
mapMutations-辅助函数
**
mapMutations
是
Vuex
提供的一个辅助函数,它简化了在
Vue
组件中提交
mutation
的过程:**
这个辅助函数允许:
store
中的
mutations
映射到组件的
methods
中,
使得你可以直接在组件的方法中调用这些
mutation
,
而不需要手动使用
this.$store.commit
;
mapMutations 使用:
Son3.vue: 和
mapState
用法类型,
mapState
针对状态数据\使用计算属性进行优化,
mapMutations
针对状态数据修改操作\使用
method
函数进行优化,**自动将事件函数名,匹配生成一个
method函数
**
<template><divclass="box"><h2>Son3 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><button@click="addCount()">值 + 1</button><!-- mutatios修改state --><button@click="addCountx(10)">值 + 10</button><!-- mutatios带 参? 修改state --><button@click="ADD_COUNTX(-10)">值 - 10</button><!-- mutatios带 参? 修改state --></div></template><script>import{ mapMutations }from'vuex';//通过ES6 语法对象解构直接获取mapMutations;exportdefault{methods:{//方式一: 直接映射名为increment的mutation...mapMutations(['ADD_COUNT','ADD_COUNTX']),//方式二: 使用对象形式来映射并重命名...mapMutations({'addCount':"ADD_COUNT",//组件方法名: store中的mutation名'addCountx':"ADD_COUNTX",}),}}</script>
注意: Vuex中mutations中不能写异步代码,如果有异步的ajax请求,应该放置在actions中;
异步操作action
在Vuex中,actions和mutations类似,是用于处理异步操作的关键部分:
它们允许你执行异步逻辑,比如API调用,并且最终通过触发一个或多个
mutations
来改变状态;
定义 actions 异步操作:
**在Vuex的
store
配置中,定义
actions
对象:** 虽然
actions
可以执行异步逻辑,但它们不能直接修改
state
相反,它们通过调用
context.commit
来触发
mutation
,从而间接改变状态,也就是说:actions依赖mutation操作state;
// 创建仓库 store 状态,即数据: // 类似于vue组件中的data、data 是组件自己的数据;// state 中的数据整个vue项目的组件都能访问到;const store =newVuex.Store({//开启严格模式strict:true,state:{count:10,title:"大标题1",},//mutations对象其中键是事件类型通常是大写命名)、值是处理函数;mutations:{//state: 表示当前Vuex中的state状态数据库,用来获取其操作数据;ADD_COUNT(state){ state.count++;},//带参传递数据: 参数只能一个,如果有多个参数,包装成一个{对象}\[数组] 传递; ADD_COUNTX(state,payload){ state.count+=payload }},//actions 处理异步: 注意,不能直接操作state 操作state 还是需要context.commit('mutation名','传参');actions:{//actions 接收参数: context对象提供了对store的访问、payload作为参数对象changeCountAction(context,num){// 这里是setTimeout模拟异步,以后大部分场景是发请求setTimeout(()=>{ context.commit('ADD_COUNTX', num)},1000)}}})
使用 actions 异步操作:
在Vue组件中,你可以通过
this.$store.dispatch('actions名','参数对象')
来触发
action
;
<template><divclass="box"><h2>Son3 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><button@click="addCount()">值 + 1</button><!-- mutatios修改state --><button@click="addCountx(10)">值 + 10</button><!-- mutatios带 参? 修改state --><button@click="ADD_COUNTX(-10)">值 - 10</button><!-- mutatios带 参? 修改state --><button@click="changeCountAction(888)">1秒后改成888</button><!-- actions 异步操作state --></div></template><script>import{ mapMutations }from'vuex';//通过ES6 语法对象解构直接获取mapMutations;exportdefault{methods:{//方式一: 直接映射名为increment的mutation//方式二: 使用对象形式来映射并重命名 ....省略....//在Vue组件中,你可以通过this.$store.dispatch来触发action:asyncchangeCountAction(x){awaitthis.$store.dispatch('changeCountAction',x);},}}</script>
mapaction-辅助函数
**
mapActions
是Vuex提供的一个辅助函数,和
mapMutations
类似,**
它允许你将
store
中的
actions
便捷地映射到
Vue
组件的
methods
中,从而简化组件内调用这些异步操作的流程;
//通过ES6 语法对象解构直接获取mapMutations...import{ mapMutations,mapActions }from'vuex';exportdefault{methods:{//mapActions 使用: 和mapMutations类似...mapActions(['changeCountAction']),...mapActions({"divChangeCountAction":"changeCountAction"}),}}
getters 类计算属性:
**
Vuex
中的
getters
是用来从
store
的状态
state
中派生出一些状态的计算属性:** 类似于组件中的
computed
计算属性;
- 计算和过滤:
getters
用于对state
进行计算和过滤,生成新的数据视图;有时我们还需要从state
中派生出一些状态,这些状态是依赖state
的,此时会用到getters
- 缓存机制:
getters
的值会被缓存,只有当其依赖的state
或其他getters
发生变化时,才会重新计算; - 访问便捷:
getters
可以通过store.getters
访问,或者在Vue
组件中通过this.$store.getters
访问;这使得多个组件可以共享这些计算后的数据,避免代码重复
getters 案例Demo
例如:
state
中定义了
list
的数组,组件中,需要显示所有大于>5的数;
// 创建仓库 store 状态,即数据: // 类似于vue组件中的data、data 是组件自己的数据;// state 中的数据整个vue项目的组件都能访问到;const store =newVuex.Store({//开启严格模式strict:true,state:{count:10,title:"大标题1",list:[1,2,3,4,5,6,7,8,9,10],},//getters 类似于计算属性,用来从 store.state 状态数据中派生出一些状态的计算属性;getters:{// state中定义了list的数组,需要显示所有大于>5的数;// 必须有返回值,返回值就是getters的值// 形参第一个参数,就是statefilterList(state){return state.list.filter(item=> item >5)}}})
Son3组件中获取:getters数据: 通过
this.$store.getters
访问定义的
getters
<template><divclass="box"><h2>Son3 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><div>getters过滤数据 {{ $store.getters.filterList }}</div></div></template>
mapgetters-辅助函数
mapGetters
提供了一种高效、简洁的方式来访问 Vuex 中的
getters
,
减少了代码冗余,增强了组件的可读性和可维护性,是 Vue 应用中状态管理的重要工具之一
<template><divclass="box"><h2>Son3 子组件</h2>
从vuex中获取的值: <label>{{ $store.state.count }}</label><div>getters过滤数据 {{ $store.getters.filterList }}</div><div>mapGetters便携获取数据 {{ filterList }}</div></div></template><script>//通过ES6 语法对象解构直接获取mapMutations...import{ mapMutations,mapActions,mapGetters }from'vuex';exportdefault{computed:{...mapGetters(['filterList']),},//组件计算函数 }</script>
版权归原作者 Java.慈祥 所有, 如有侵权,请联系我们删除。