Vuex@3
什么是Vuex?
Vuex是由Vue提供的可以用于
全局数据共享
,集中式
存储管理,并且提供一套可操作的流程来获取与操作数据
。(集中式相当于一位老师同时教好几十个学生,分布式相当于一对一的家教)
什么时候用Vuex?
简而言之,当
多个组件
需要操作同一个数据
的时候。也就是需要数据共享
的时候,可以考虑用Vuex。或者在其他通信,例如父子通信、爷孙通信、兄弟通信过于麻烦的时候,也可以考虑使用Vuex。
Vuex的利弊?
-
好处当然是可以多组件
数据共享
。 -
弊端同样也是数据共享。数据共享所带来的一个问题,
当修改某个组件内的数据时,会对其他组件造成影响
。
对比mixins
在vue2项目开发的时候,我们通常会把一些具有共性的变量,方法,钩子函数,或监听写在一个js文件内,然后通过mixins引入到组件中。
每次引入都会形成新的代码
,即不会发生在某个组件内修改js文件内变量的值,导致其他组件收到影响。
为什么标题叫Vuex@3?
我们在
安装Vuex插件
的时候,使用npm i vuex
默认安装的是Vuex4.+版本,这些版本只支持Vue3。所以在Vue2项目中要使用Vuex3.+版本,也就是npm i vuex@3
,其中@3
也就是指定的Vuex版本号。
通过官方提供的图来初步认识下Vuex
上面的图片来自Vuex的官网:vuex.vuejs.org/zh/接下来主要介绍一下这张图片的意思。该模块主要介绍Vuex主要的
三大对象
,以及通信的流程
,并不涉及代码。
- 首先,我们看一下绿色虚线里面的内容(Actions、Mutations、State),这三个对象是Vuex的核心,主要涉及了数据的
行为(Actions)
,数据的操作(Mutations)
,以及数据的存储(State)
,这三个对象由store
进行管理。- 其次,看一下实线箭头的内容(Dispatch、Commit、Mutate、Render):
- Vue的组件通过
Dispatch
方法,匹配Actions对象中对应的函数,该函数会触发Commit
函数,匹配Mutations中与之对应的函数进行对数据的操作,将操作完的数据替换State对象中对应的数据,最终Render渲染在组件中进行展示。- 然后,看一下两个虚线箭头(Backend API和Devtools):
Dispatch联系的Actions
上的虚线箭头(Backend API),主要用于处理业务逻辑或者是异步请求
。如果没有上述的两大需求,组件可以直接通过Commit联系Mutations
;- Devtools主要是帮助开发的调试工具,可以更加直观地观察数据操作的过程。
- 最后,说一下上面图片没有展示出来的两个对象:
Getters
和Modules
。
- Getters主要用于对state对象中数据进行
数学运算、过滤等不会改变原有值的操作
;- Modules主要用于模块化,使得不同模块的
代码分离,方便维护,更加清晰
。
代码实践
-
第一步,安装插件
npm i vuex@3
或者yarn add vuex@3
; -
第二步,在vue项目中
创建store
以及引入store
;-
创建store(在src根目录下,创建store文件夹,并在该文件夹内添加
index.js
文件)
为什么要把Vue.use(Vuex)写在index.js文件内是为了防止报错(import提升执行index.js文件的时候,导致找不到Vuex) -
引入store:
在main.js
文件中import store from "./store";
并且在new Vue({ store })
对象中添加store。
-
-
完成上面这一步后,就可以在组件中使用
this.$store
打印查看Vuex强大的内容了; -
第三步,在刚刚创建的index.js文件内三大核心对象里面写点东西了;
-
-
第四步,来用一用
dispatch
、commit
、getters
和state
;-
当我们需要对首字母进行判断,并为C时再进行对应的数据操作时,可以用dispatch。
this.$store.dispatch('test', value);
其中test对应的是actions对象中的test函数,value为值,可以自行填写。 -
当不需要业务或者异步请求操作的时候,可以直接使用commit进行数据操作。
this.$store.commit('TEST', value);
其中,TEST对应mutations对象中的TEST函数,value同样为值,同理。 -
当我们想对state中数据特殊处理,但是又不想影响其他使用该数据的组件时,可以用getters。
this.$store.getters.getName
其中getName为getters对象中的getName函数。 -
当我们想直接读取state中数据时
this.$store.state.name
其中name为state对象中的name属性。
-
-
最后来说一说模块化
modules
(注意js文件中的差异)-
这边我就暂时不把test1和test2抽离出去新建两个js文件然后向外暴露了。
-
使用模块化后,对应的
dispatch
、commit
、getters
和state
读取操作数据会有所不同。- state:
this.$store.state.模块名称.state对象中的属性名;
- dispatch:
this.$store.dispatch('模块名称/actions对象中的属性名', value);
- commit:
this.$store.commit('模块名称/mutations对象中的属性名', value);
- getters:
this.$store.getters['模块名称/getters对象中的属性名'];
- state:
-
-
可以很清楚地看到,
模块化后的操作很繁琐
,下面介绍如何优化代码(先说说模块化之前的优化)- 首先要引入:
import { mapState } from 'vuex';
- mapState(map为映射的意思,写在computed计算中)
- 对象法:
mapState({ '函数名': 'state中对应的名字' });
- 数组法:
mapState([ '函数名' ]);
当函数名和state中保存的数据名相同时使用数组法
- 对象法:
- 下面三个
以此类推
- mapGetters(写在computed计算中)
- mapActions(写在methods方法中)
- mapMutations(写在methods方法中)
- 首先要引入:
-
介绍在模块下的场景下优化代码(需要在模块化代码下添加命名空间
namespaced: true
,详情见第六条的代码)- mapState(写在computed计算中)
- 对象法:
mapState('模块名', { '函数名': 'state中对应的名字' });
- 数组法:
mapState('模块名', [ '函数名' ]);
当函数名和state中保存的数据名相同时使用数组法
- 对象法:
- 下面三个
以此类推
- mapGetters(写在computed计算中)
- mapActions(写在methods方法中)
- mapMutations(写在methods方法中)
- mapState(写在computed计算中)
总结
本章节主要介绍了Vuex的三个核心对象,且这三个核心对象由store进行管理。以及dispatch、commit、getters、modules以及代码优化。
预言
下一次再见,我会把路由相关学习的内容整理后并争取实现一个动态路由。