Vuex - 组件全局状态(数据)管理机制
总结:
组件全局状态(数据)管理机制Vuex的安装、导入及使用:
四大核心概念使用:
1. State 存储数据
(1)this.$store.state.全局数据名称
(2)import { mapState } from 'vuex'
——computed: { ...mapState(['count']) }
2. Mutation 修改数据(同步)
(1)this.$store.commit('addN', 3) // 触发时,携带参数
(2)import { mapMutations } from 'vuex'
——methods: { ...mapMutations(['add','addN']) }
3. Action 处理异步逻辑,并触发 Mutation 以间接更新 State
(1)this.$store.dispatch('addNAsync', 3) // 携带参数
(2)import { mapActions } from 'vuex'
——methods: { ...mapAction(['addAsync','addNAsync']) }
4. Getter 提供数据加工
(1)this.$store.getters.名称
(2)import { mapGetters } from 'vuex'
——computed: { ...mapGetters(['showNum']) }
概述
组件之间共享数据的方式
父向子:porps自定义属性
子向父:自定义事件$.emit
、v-on/@
兄弟组件之间:EventBus$.emit
、$.on
这三种的方式,只适合在小范围内来进行数据的共享
如果需要频繁的,或者大范围的来实现数据的共享,这三种方案就有些力不从心Vuex
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
Vuex就相当于在这些组件旁边定义了一个共享的数据状态对象Store使用Vuex统一管理状态的好处
- 能够在vuex中集中管理共享的数据,易于开发和后期维护
- 能够高效地实现组件之间的数据共享,提高开发效率
- 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步
什么样的数据适合存储到Vuex中
一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;对于组件中的私有数据,依旧存储在组件自身的data中即可。
基本使用
- 安装vuex依赖包:
npm i vuex -S
- 导入vuex包
import Vuex from 'vuex'
Vue.use(Vuex)
- 创建store对象
1
2
3
4const store = new Vuex.Store({
// state中存放的就是全局共享的数据
state: { count: 0 }
}) - 将store对象挂载到vue实例中
1
2
3
4
5
6
7
8new Vue({
el: '#app',
render: h => h(app),
router,
// 将创建的共享数据对象,挂载到Vue实例中
// 所有的组件,就可以直接从store中获取全局的数据了
store
})
创建vue项目时,如果添加了vuex的配置,会自动帮我们配置好这些
核心概念
Vuex中主要的核心概念如下:
- State
- Mutation
- Action
- Getter
总结来说,State 存储数据,Getter 提供数据加工,Mutation 修改数据(同步),而 Action 处理异步逻辑并触发 Mutation 以间接更新 State。这四者共同构成了 Vuex 的核心机制,帮助开发者更好地管理和维护应用的状态。
State
State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储。
组件访问State中数据的方式一:直接访问
this.$store.state.全局数据名称
,如this.$store.state.count
组件访问State中数据的方式二:使用mapState辅助函数
- 从vuex中按需导入mapState函数
import { mapState } from 'vuex'
- 通过mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性 或者使用对象展开语法进行更细致的映射:
1
2
3computed: {
...mapState(['count'])
}1
2
3
4
5computed: {
...mapState({
localCount: state => state.count
})
}
- 从vuex中按需导入mapState函数
使用方式建议
- 只需要访问一两个State属性,且不频繁使用 —— 直接访问
- 访问多个State属性,或者需要对State数据进行一些转换处理 —— mapState辅助函数
更加清晰和高效,使代码更模块化,易于阅读和维护。
- 项目使用了TS —— mapState辅助函数
mapState配合类型注解可以提供更好的类型安全性。
总的来说,选择哪种方式取决于具体场景和个人偏好,但通常推荐使用mapState,因为它可以让你的代码更加整洁、易于维护,并且在处理复杂逻辑时更为灵活。
Mutation
在组件中,虽然可以
this.$store.state.count = 1
直接修改全局的数据,且不报错,
但是在Vuex中,它不允许组件直接去修改Store的数据,而是推荐使用Mutation
Mutation用于变更Store中的数据。
通过这种方式虽然操作稍微繁琐一些,但是可以集中监控所有数据的变化
通过
this.$store.state.count = 1
修改数据,如果想看一下是谁修改的,需要挨个组件去翻,不利于后期维护。
通过Mutation
里面的函数修改数据,如果发现数据修改有问题,可以直接找对应的Mutation
定义Mutations
1 | const store = new Vuex.Store({ |
- 传递参数
1 | const store = new Vuex.Store({ |
触发方式一
1 | methods: { |
触发方式二
- 从Vuex中按需导入 mapMutations 函数:
import { mapMutations } from 'vuex'
注意是小写的vuex
- 通过mapMutations函数,将需要的mutations函数,映射为当前组件的methods方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17methods: {
...mapMutations(['add','addN'])
}
// 可以直接调用
<button @click="add">count +1</button>
<button @click="addN(3)">count +3</button> // 携带参数
// 也可以在方法中调用 -- 推荐
methods: {
...mapMutations(['add','addN']),
btnHandle1(){
this.add()
},
btnHandle2(){
this.addN(3) // 携带参数
}
}
Action
在Mutations函数中,不能写异步的代码(setTimeout、setIterval等),虽然页面效果没有问题,但是数据没有传到state,会导致在devtools提交更新后,页面的数据又恢复原来的了
Action 用于处理异步任务
但是在Action中,还是要通过触发Mutation的方式间接变更数据
定义Action
1 | const store = new Vuex.store({ |
- 传参
1 | const store = new Vuex.store({ |
触发Action - 方式一
1 | methods: { |
触发Action - 方式二
和Mutations一样
- 从Vuex中按需导入 mapActions 函数:
import { mapActions } from 'vuex'
注意是小写的vuex
- 通过mapActions函数,将需要的actions函数,映射为当前组件的methods方法:
1
2
3methods: {
...mapActions(['addAsync','addNAsync'])
}
Getter
Getter用于对Store中的数据进行加工处理形成新的数据。起到一个包装数据的作用,类似计算属性computed
- 定义Getter
1
2
3
4
5
6
7
8
9
10const store = new Vuex.store({
state: {
count: 0
},
getters: {
showNum: state=>{
return '当前最新的数量是【' + state.count +'】'
}
}
})
Getters的使用同样和State一致
使用Getter方式一
this.$store.getters.名称
如:this.$store.getters.showNum
使用Getter方式二 —— mapGetters
- 从vuex中按需导入mapGetters函数
import { mapGetters } from 'vuex'
- 通过mapGetters函数,将当前组件需要的getters,映射为当前组件的computed计算属性
1
2
3computed: {
...mapGetters(['showNum'])
}
- 从vuex中按需导入mapGetters函数
关于核心概念的使用方式
就像state中说到的那样:
- 使用不频繁 —— 直接访问
- 访问多次,或者需要进行转换处理 —— mapXXX辅助函数
更加清晰和高效,使代码更模块化,易于阅读和维护。
- 项目使用了TS —— mapXXX辅助函数
mapXXX辅助函数配合类型注解可以提供更好的类型安全性。
总的来说,选择哪种方式取决于具体场景和个人偏好,但通常推荐使用mapXXX辅助函数,因为它可以让你的代码更加整洁、易于维护,并且在处理复杂逻辑时更为灵活。