使用vuex实现任意组件间通信
学习vue的第五天,学到了用插件vuex来实现vue任意组件之间的通信。
以下是个人理解,如有错误请指正。
vuex描述
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex实现了共享数据的功能,当一个组件想要获取数据时直接向vuex发送请求即可,当一个组件想修改vuex中的数据时可以通过显式调用dispatch和commit来对vuex管理的状态进行修改。
这个图片vuex官网贴的一张vuex内部逻辑图片,左边绿色的是组件
- 当一个组件想要修改vuex管理的数据(state)时,可以 通过调用dispatch方法,需要传递两个参数,第一个是string类型的传入的是Actions中的方法名,第二个是要向方法中传递的参数value。
- 当Actions接收到一个dispatch时,会向自身去寻找是否有第一个参数的方法名,如果没有就提示错误,找到之后就将第二个参数传入该方法。在Actions中的方法一般有两个参数,第一个是context也就是将vuex本身的一些方法包括(commit、state、dispatch······)这些传给方法,方便在逻辑处理之后进行下一步操作,第二个参数就是value,也就是用户传入的数据,如果是单数据就可以直接用,多数据的话可以传对象。
- 在Actions中处理逻辑之后一方面可以再次调用dispatch进行下一个阶段的逻辑处理,另一个是直接调用commit将操作发送到Mutations中。当然组件也可以直接通过commit方法向Mutations传。这里有两个参数,第一个是Mutations中的方法名(string),第二个是要操作的数据。
- Mutations中的方法在检测到有调用时会收到两个参数,第一个是state,也就是vuex储存的数据,第二个是组件要传入的数据。这时就可以进行操作将state中的数据进行更新。
- 当state中的数据更新后,用到数据的组件也会进行重新的渲染。
由于整个流程中只有Mutations中的方法在真正的操作state中的数据,所以vue开发者工具的监测只针对Mutations。在Actions中可以进行一些复杂的逻辑操作,也可以向其他的服务器发送信息等来验证自己的数据是否合理。
vuex安装配置
上面整理完vuex的工作流程,这里是vuex的安装。
通过npm install vuex@3
进行安装即可,这里有一个点是如果使用的是vue2.0的版本,那么vuex就应该下载3.0版本,因为vuex的4.0版本是为vue3.0服务的,所以在npm安装的时候要注意一下选择版本号。
安装完成之后就可以开始配置了。
因为vuex是一个全局的状态管理,有点类似全局事件总线,所以应该将vuex安装在vue实例对象身上,这样任意组件都可以访问到vuex。vuex在vue的配置中叫store
,在创建vue实例的时候将其配置到对象中即可。
可以看到这里有一个store是通过外部引入的,这个就是vuex的配置文件,在src下创建一个store
文件夹,文件夹里创建一个index.js
文件用来写vuex的配置。
插件的安装需要用到Vue.use(),方法,所以在这个文件中也要引入vue。引入vuex之后,可以开始配置了。
上面图中看到vuex的store中有三个主要的内容也可以说是配置对象,就是actions、mutations、state,在文件中创建三个对象
- actions中要写的是用于响应组件中的动作回调函数,组件通过dispatch方法调用actions中的方法,回调函数接收到的参数有两个(context, value),可以完成一些逻辑,然后将操作传向mutations。
- mutations中写的是操作state的函数,会被actions和组件通过commit调用,回调函数接收到的参数有两个(state, value)。
- state中写的就是储存的数据。
- 下面代码也提到了getters配置项,它就像组件中的computed计算属性,将一些计算后的数据返回,组件可以通过getters点得到想要的内容。
写完配置项之后就可以创建store也就vuex实例了,调用Vuex的Store方法,传入前面写好的四个配置项,然后将new出来的store默认暴露即可,之后在main.js中配置到Vue实例对象上,就可以发现实例对象身上出现了一个$store
的值,打开之后就是vuex的方法和state数据。
1 | // store/index.js内容 |
vuex使用
单模块
配置完之后就可以使用了,在组件中通过$store
拿到vuex的数据。
拿到state数据中的sum数据
1
this.$store.state.sum
拿到getters中的数据
1
this.$store.getters.bigSum
向actions发送
1
this.$store.dispatch('incrementOdd', this.n)
向mutations发送
1
this.$store.commit('DECREMENT',this.n)
上面是最基本的拿到store中的数据。
下面是去拿这些数据的简写方法也就是vuex的一些封装好的方法
导入方法
1
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
拿state和getters数据(将数据通过计算属性拿到之后就可以在模板中直接调用),这里mapState和mapGetters拿到的数据是函数对象,通过…将对象展开到计算属性中。
1
2
3
4
5
6
7
8
9
10
11computed: {
// 借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({sum:'sum'})
// 借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum']),
// 借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
// ...mapGetters({bigSum:'bigSum'})
// 借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])
},通过mapMutations和mapActions生成调用函数,这里生成的函数可以有传参,不过需要在标签调用时直接传入,否则会将事件event传入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28methods: {
// 自己写的方法调用commit
// increment(){
// this.$store.commit('INCREMENT',this.n)
// },
// decrement(){
// this.$store.commit('DECREMENT',this.n)
// },
// 借助mapMutations生成对应的方法,方法会调用commit方法联系mutations(对象写法)
// 需要调用时传参value,否则传参为event
...mapMutations({increment:'INCREMENT', decrement:'DECREMENT'}),
// 借助mapMutations生成对应的方法,方法会调用commit方法联系mutations(数组写法)
// ...mapMutations(['INCREMENT','DECREMENT'])
// 自己写的方法调用dispatch
// incrementOdd(){
// this.$store.dispatch('incrementOdd', this.n)
// },
// incrementWait(){
// this.$store.dispatch('incrementWait', this.n)
// },
// 借助mapActions生成对应的方法,方法会调用dispatch方法联系actions(对象写法)
// 需要调用时传参value,否则传参为event
// ...mapActions({incrementOdd:'incrementOdd', incrementWait:'incrementWait'}),
// 借助mapActions生成对应的方法,方法会调用dispatch方法联系actions(数组写法)
...mapActions(['incrementOdd','incrementWait'])
},
多模块
上面的store配置是单模块的,如果多人开发,就会出现冲突问题,下面通过命名空间多模块,来解决。
index.js中
- 将两个组件的数据分别配置在两个对象中,打开namespaced配置为true,在下面new store时传入模块。
1 | import Vue from 'vue' |
组件中调用时
简写方式,在mapState函数中传入第一个参数,也就是模块的命名名称。
1
2
3
4...mapState('countOptions',['sum']),
...mapGetters('countOptions',['bigSum']),
...mapMutations('countOptions',{increment:'INCREMENT', decrement:'DECREMENT'}),
...mapActions('countOptions',['incrementOdd','incrementWait']),未简写方式
1
2
3
4
5
6
7// 获取state中的数据时需要先获取命名对象,再获取想要的数据
this.$store.state.countOptions.sum
// 获取getters时需要在getters的对象名称前加上命名名称/
this.$store.getters['studentOptions/firstStudentName']
// 向actions和mutations传时需要修改传入的第一个参数,在方法名前加上命名名称/
this.$store.commit('studentOptions/ADDSTUDENT', studentObj)
this.$store.dispatch('studentOptions/addWangStudent', studentObj)