Vue数据共享之Vuex

55 阅读5分钟

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.png

上面的图片来自Vuex的官网:vuex.vuejs.org/zh/接下来主要介绍一下这张图片的意思。该模块主要介绍Vuex主要的三大对象,以及通信的流程,并不涉及代码。

  1. 首先,我们看一下绿色虚线里面的内容(Actions、Mutations、State),这三个对象是Vuex的核心,主要涉及了数据的行为(Actions),数据的操作(Mutations),以及数据的存储(State),这三个对象由store进行管理。
  2. 其次,看一下实线箭头的内容(Dispatch、Commit、Mutate、Render):
    • Vue的组件通过Dispatch方法,匹配Actions对象中对应的函数,该函数会触发Commit函数,匹配Mutations中与之对应的函数进行对数据的操作,将操作完的数据替换State对象中对应的数据,最终Render渲染在组件中进行展示。
  3. 然后,看一下两个虚线箭头(Backend API和Devtools):
    • Dispatch联系的Actions上的虚线箭头(Backend API),主要用于处理业务逻辑或者是异步请求。如果没有上述的两大需求,组件可以直接通过Commit联系Mutations
    • Devtools主要是帮助开发的调试工具,可以更加直观地观察数据操作的过程。
  4. 最后,说一下上面图片没有展示出来的两个对象:GettersModules
    • Getters主要用于对state对象中数据进行数学运算、过滤等不会改变原有值的操作
    • Modules主要用于模块化,使得不同模块的代码分离,方便维护,更加清晰

代码实践

  1. 第一步,安装插件npm i vuex@3或者yarn add vuex@3

  2. 第二步,在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。

  3. 完成上面这一步后,就可以在组件中使用this.$store打印查看Vuex强大的内容了;

  4. 第三步,在刚刚创建的index.js文件内三大核心对象里面写点东西了;

  5. 第四步,来用一用dispatchcommitgettersstate

    • 当我们需要对首字母进行判断,并为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属性。

  6. 最后来说一说模块化modules(注意js文件中的差异)

    • 这边我就暂时不把test1和test2抽离出去新建两个js文件然后向外暴露了。

    • 使用模块化后,对应的dispatchcommitgettersstate读取操作数据会有所不同。

      1. state:this.$store.state.模块名称.state对象中的属性名;
      2. dispatch: this.$store.dispatch('模块名称/actions对象中的属性名', value);
      3. commit:this.$store.commit('模块名称/mutations对象中的属性名', value);
      4. getters:this.$store.getters['模块名称/getters对象中的属性名'];
  7. 可以很清楚地看到,模块化后的操作很繁琐,下面介绍如何优化代码(先说说模块化之前的优化)

    • 首先要引入:import { mapState } from 'vuex';
    • mapState(map为映射的意思,写在computed计算中)
      • 对象法:mapState({ '函数名': 'state中对应的名字' });
      • 数组法:mapState([ '函数名' ]);当函数名和state中保存的数据名相同时使用数组法
    • 下面三个以此类推
      • mapGetters(写在computed计算中)
      • mapActions(写在methods方法中)
      • mapMutations(写在methods方法中)
  8. 介绍在模块下的场景下优化代码(需要在模块化代码下添加命名空间namespaced: true,详情见第六条的代码)

    • mapState(写在computed计算中)
      • 对象法:mapState('模块名', { '函数名': 'state中对应的名字' });
      • 数组法:mapState('模块名', [ '函数名' ]);当函数名和state中保存的数据名相同时使用数组法
    • 下面三个以此类推
      • mapGetters(写在computed计算中)
      • mapActions(写在methods方法中)
      • mapMutations(写在methods方法中)

总结

本章节主要介绍了Vuex的三个核心对象,且这三个核心对象由store进行管理。以及dispatch、commit、getters、modules以及代码优化。

预言

下一次再见,我会把路由相关学习的内容整理后并争取实现一个动态路由。