【Vuex】核心概念解读

快来打我* 2023-02-25 08:49 127阅读 0赞

目标

知道什么是Vuex
掌握Vuex的基本使用
掌握Vuex的核心概念及其用法

1. Vuex是什么

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。了解更多——传送官网:https://vuex.vuejs.org/zh/

1.1 组件之间共享数据的方式

父向子传值:v-bind 属性绑定
子向父传值:v-on 事件绑定
兄弟组件之间共享数据: EventBus

  • $on 接收数据的那个组件
  • $emit 发送数据的那个组件
1.2 使用Vuex传值方式

Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。

在这里插入图片描述

1.3 使用 Vuex 统一管理状态的好处

①: 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
②: 能够高效地实现组件之间的数据共享,提高开发效率
③: 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步

1.4 什么样的数据适合存储到 Vuex 中

一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件
自身的 data 中即可。

2. Vuex 的基本使用

2.1 安装 vuex 依赖包

可通过可视化UI 面板安装依赖 Vuex。也可以npm 命令安装npm install vuex --save

2.2 导入 vuex 包
  1. import Vuex from 'vuex'
  2. Vue.use(Vuex)
2.3 创建 store 对象
  1. const store = new Vuex.Store({
  2. // state 中存放的就是全局共享的数据
  3. state: { count: 0 }
  4. })
2.4 将 store 对象挂载到 vue 实例中
  1. new Vue({
  2. el: '#app',
  3. render: h => h(app),
  4. router,
  5. // 将创建的共享数据对象,挂载到 Vue 实例中
  6. // 所有的组件,就可以直接从 store 中获取全局的数据了
  7. store
  8. })

3. 核心概念概述

Vuex 中的主要核心概念包含:State 、Mutation 、Action 、Getter

3.1 State

State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。

示例:

  1. // 创建store数据源,提供唯一公共数据
  2. const store = new Vuex.Store({
  3. state: { count: 0 }
  4. })

组件访问state中数据的第一种方式

  1. this.$store.state.全局数据名称

组件访问state中数据的第二种方式

  1. // 1. 从 vuex 中按需导入 mapState 函数
  2. import { mapState } from 'vuex'
  3. // 2. 将全局数据,映射为当前组件的计算属性
  4. computed: {
  5. ...mapState(['count'])
  6. }

注意:此处通过刚才导入的 mapState 函数,将当前组件需要的全局数据映射为当前组件的 computed 计算属性

3.2 Mutation

Mutation 用于变更 Store中 的数据

①: 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。
②: 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
③:mutations中的的函数一定要有state参数

示例:

  1. // 定义 Mutation
  2. const store = new Vuex.Store({
  3. state: {
  4. count: 0
  5. },
  6. mutations: {
  7. add(state) {
  8. // 变更状态
  9. state.count++
  10. }
  11. }
  12. })
  13. // 触发mutation
  14. methods: {
  15. handle1() {
  16. // 触发 mutations 的第一种方式(也可直接将mutation函数写在事件函数处)
  17. this.$store.commit('add')
  18. }
  19. }

▶:可以在触发 mutations 时传递参数

示例:

  1. // 定义Mutation
  2. const store = new Vuex.Store({
  3. state: {
  4. count: 0
  5. },
  6. mutations: {
  7. addN(state, step) {
  8. // 变更状态
  9. state.count += step
  10. }
  11. }
  12. })
  13. // 触发mutation
  14. methods: {
  15. handle2() {
  16. // 在调用 commit 函数,
  17. // 触发 mutations 时携带参数
  18. this.$store.commit('addN', 3)
  19. }
  20. }

▶:触发 mutations 的第二种方式

示例:

  1. // 1. 从 vuex 中按需导入 mapMutations 函数
  2. import { mapMutations } from 'vuex'
  3. // 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
  4. methods: {
  5. ...mapMutations(['add', 'addN'])
  6. }

注意:此处通过刚才导入的 mapMutations 函数,将需要的 mutations 函数映射为当前组件的 methods 方法

3.3 Action

Action 用于处理异步任务

如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发 Mutation 的方式间接变更数据

示例:

  1. // 定义 Action
  2. const store = new Vuex.Store({
  3. // ...省略其他代码
  4. mutations: {
  5. add(state) {
  6. state.count++
  7. }
  8. },
  9. actions: {
  10. addAsync(context) {
  11. setTimeout(() => {
  12. context.commit('add')
  13. }, 1000)
  14. }
  15. }
  16. })
  17. // 触发 Action
  18. methods: {
  19. handle() {
  20. // 触发 actions 的第一种方式
  21. this.$store.dispatch('addAsync')
  22. }
  23. }

▶:触发 actions 异步任务时携带参数

示例:

  1. // 定义 Action
  2. const store = new Vuex.Store({
  3. // ...省略其他代码
  4. mutations: {
  5. addN(state, step) {
  6. state.count += step
  7. }
  8. },
  9. actions: {
  10. addNAsync(context, step) {
  11. setTimeout(() => {
  12. context.commit('addN', step)
  13. }, 1000)
  14. }
  15. }
  16. })
  17. // 触发 Action
  18. methods: {
  19. handle() {
  20. // 在调用 dispatch 函数,
  21. // 触发 actions 时携带参数
  22. this.$store.dispatch('addNAsync', 5)
  23. }
  24. }

▶:触发 actions 的第二种方式

示例:

  1. // 1. 从 vuex 中按需导入 mapActions 函数
  2. import { mapActions } from 'vuex'
  3. // 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
  4. methods: {
  5. ...mapActions(['addASync', 'addNASync'])
  6. }

注意:此处通过刚才导入的 mapActions 函数,将需要的 actions 函数映射为当前组件的 methods 方法

3.4 Getter

Getter 用于对 Store 中的数据进行加工处理形成新的数据

①: Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
②: Store 中数据发生变化,Getter 的数据也会跟着变化。

示例:

  1. // 定义 Getter
  2. const store = new Vuex.Store({
  3. state: {
  4. count: 0
  5. },
  6. getters: {
  7. showNum: state => {
  8. return '当前最新的数量是【'+ state.count +'】'
  9. }
  10. }
  11. })

▶:使用 getters 的第一种方式

  1. this.$store.getters.名称

▶:使用 getters 的第二种方式

  1. import { mapGetters } from 'vuex'
  2. computed: {
  3. ...mapGetters(['showNum'])
  4. }

4. 综合本文代码的案例

对本文中 Vuex 的核心概念,进行了详尽的展示(通过调试工具,直观的展现数据的响应式变化)

4.1 效果预览

在这里插入图片描述

4.2 实现步骤
  1. 首先创建 含vuex 的 vue项目
  2. 然后修改App根组件,新增加法、减法两个新组建,实现页面基本布局
  3. store.js文件中需要管理的数据

    import Vue from ‘vue’
    import Vuex from ‘vuex’

    Vue.use(Vuex)

    export default new Vuex.Store({

    1. state: {
    2. num: 0
    3. },
    4. mutations: {
    5. //# 只有mutations中的函数才有权限修改state中的数据
    6. add1(state) {
    7. state.num++
    8. },
    9. sub1(state) {
    10. state.num--
    11. },
    12. addN(state, step) {
    13. state.num += step
    14. },
    15. subN(state, step) {
    16. state.num -= step
    17. }
    18. },
    19. actions: {
    20. //# 主要用于处理异步操作
    21. AddAsync(context) {
    22. setTimeout(() => {
    23. //# 在action中,不能直接修改state中的数据
    24. //# 必须通过 context.commit() 触发某个mutation 才行
    25. context.commit('add1')
    26. }, 1000)
    27. },
    28. SubAsync(context) {
    29. setTimeout(() => {
    30. //# 在action中,不能直接修改state中的数据
    31. //# 必须通过 context.commit() 触发某个mutation 才行
    32. context.commit('sub1')
    33. }, 1000)
    34. },
    35. //# 主要用于处理异步操作
    36. AddNAsync(context, step) {
    37. setTimeout(() => {
    38. context.commit('addN', step)
    39. }, 1000)
    40. },
    41. SubNAsync(context, step) {
    42. setTimeout(() => {
    43. context.commit('subN', step)
    44. }, 1000)
    45. }
    46. },
    47. getters: {
    48. showNum(state) {
    49. return '当前最新数值为【' + state.num + '】'
    50. }
    51. },
    52. modules: { }

    })

  4. 两个组件使用 state 中的数据

组件1:

  1. <template>
  2. <div>
  3. <!-- 第一种获取store数据的方法 -->
  4. <h1>{ { this.$store.getters.showNum}}</h1>
  5. <!-- 也可以直接在事件后写mutation函数(需要去除this,此处this指向button) -->
  6. <button @click="$store.commit('add1')">点击+1</button>
  7. <button @click="handle1">点击+3</button>
  8. <button @click="handle2">1秒后+1</button>
  9. <button @click="handle3">1秒后+5</button>
  10. </div>
  11. </template>
  12. <script>
  13. export default {
  14. methods: {
  15. handle1() {
  16. this.$store.commit('addN', 3);
  17. },
  18. handle2() {
  19. this.$store.dispatch('AddAsync');
  20. },
  21. handle3() {
  22. this.$store.dispatch('AddNAsync', 5);
  23. }
  24. }
  25. };
  26. </script>

组件2:

  1. <template>
  2. <div>
  3. <!-- 此处为使用store数据的第二种方式 -->
  4. <h1>{ { showNum}}</h1>
  5. <button @click="sub1">点击-1</button>
  6. <button @click="handle">点击-2</button>
  7. <button @click="subN(2)">点击-2</button>
  8. <button @click="SubAsync">1秒后-1</button>
  9. <button @click="SubNAsync(4)">1秒后-4</button>
  10. </div>
  11. </template>
  12. <script>
  13. import { mapState, mapGetters } from 'vuex';
  14. import { mapMutations } from 'vuex';
  15. import { mapActions } from 'vuex';
  16. export default {
  17. data() {
  18. return { };
  19. },
  20. computed: {
  21. ...mapState(['num']),
  22. ...mapGetters(['showNum'])
  23. },
  24. methods: {
  25. ...mapMutations(['sub1', 'subN']),
  26. ...mapActions(['SubAsync', 'SubNAsync']),
  27. //# 也可以把metations函数写在组件本身的函数中
  28. handle() {
  29. this.subN(2);
  30. }
  31. }
  32. };
  33. </script>

over

加油,一切都很值得!

发表评论

表情:
评论列表 (有 0 条评论,127人围观)

还没有评论,来说两句吧...

相关阅读