vuex

本文介绍了Vuex作为Vue的状态管理模式,用于管理多个组件间的共享数据。Vuex的核心概念包括state(存储状态)、getters(计算属性)、mutations(同步修改状态)和actions(处理异步操作)。文章通过实例演示了Vuex的安装、基本使用以及如何在组件中访问和修改状态。同时,提到了Vuex的modules特性,用于模块化状态管理,以及遵守的规范和最佳实践。
摘要由CSDN通过智能技术生成

四、Vuex

                                     ps:仅供本人记忆

4.1 认识Vuex

4.1.1 什么是Vuex

  • Vuex是一个状态管理模式
  • 他可以将多个组件间需要共享的数据(状态),保存在一个容器中(store)。
  • 每个组件可以直接获取修改这些共享的数据(状态)
    • Vuex 的状态存储是响应式的,若 容器(store) 中的数据发生变化,则会重新渲染对应页面视图

4.1.2 单组件状态管理

  • 在单个组件中进行状态管理是一件非常简单的事情
  • 每个组件有属于自己的数据(data)、行为(methods)、视图(html模板)
    • data往往是通过methods进行改变,data改变后其组件的视图也会发生更新

 

  • 可以通过计时器案例加深对这张图的理解

4.1.3 多组件状态管理

  • 多页面状态管理核心:多个视图都依赖同一个状态(数据)(一个状态改了,多个界面需要进行更新)
  • Vuex就是为我们提供存储多个共享状态的工具。
  • 全局单例模式(大管家)
    • 我们现在要做的就是将共享的状态抽取出来,交给Vuex统一进行管理。
    • 之后每个组件,按照Vuex制定的规范,进行访问和修改等操作。
    • 这就是Vuex背后的基本思想。
  • Vuex状态管理图例

 

4.1.4 Vuex的基本使用

  1. 通过vue-cli搭建项目时,选择vuex包,或者自己手动下载vuex包
  2. 在src目录下,新建一个store文件夹,里面新建一个index.js文件,用于存放Vuex相关代码

 

  1. 编写Vuex相关代码

 

  1. 在项目的入口JS文件中,导入Vuex实例,并写入Vue的配置选项中

 

    • 将Vuex实例挂载到Vue的配置选项上时,其他所有组件的$store其实就是入口JS文件中导入的store
  • 在其他组件中,可以通过this.$store的方式,获取到这个store对象

 

    • 上图中methods下的方法的return可以去掉
  • 注意事项:Vuex并不允许直接在组件中改变共享的数据,而是要通过提交mutation的方式来修改共享的数据
    • 只有这样,谷歌浏览器插件Vue.js devtools才能够实时记录共享数据的改变

 

4.2 Vue核心概念

  • Vuex有几个比较核心的概念,而这几个核心概念正是创建Vuex实例时,所要传入的配置对象
    • // 创建Vuex实例
      const store = new Vuex.Store({
         
      state: {},
      getters: {},
         
      mutations: {},
         
      actions: {},
         
      modules: {}
      })

4.2.1 State

  • 类型:Object
  • 详细:
    • 用于定义Vuex中一些共享的状态(数据),其他组件可以通过this.$store.state.xxx来获取共享的数据
  • 示例:
    • const store = new Vuex.Store({
         
      state: {
             
      count: 0
        }
      }

      // 其他组件可以访问this.$store.state.count数据

4.2.2 Getters

  • 类型:{ [key: string]: Function }
  • 详细:
    • Getters类似于组件的计算属性,用于对state中的数据进行加工过滤操作,所有组件都可以通过this.$store.getters.xxx访问getters下所有定义的属性
  • Getters中的内部方法可以接受两个参数
    • 第一个参数为state,可以直接通过state.xxx获取定义在state下的属性
    • 第二个参数为getters,可以通过getters.xxx获取定义在getters下的属性
    • Getters中的内部方法,必须要有返回值
    • 虽然Getters内部是写的方法,但是Vuex会将他内部的方法解析为store.getters下的属性

 

  • 示例:

 

  • 如果希望getters下定义的方法能够接受参数,则要使用如下写法

 

辅助函数

  • mapGetters 辅助函数仅仅是将 store 中的 getter 映射到组件的计算属性中

 

    • 上图代码中,将Vuex -> getters -> cartLength 计算属性映射为组件中的 this.cartLength
  • 如果你想将一个 getter 属性另取一个名字,使用对象形式
    • ...mapGetters({
       
      // `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
       doneCount: 'doneTodosCount'
      })
  • 除了mapGetters辅助函数,Vuex还提供了mapActions、mapState辅助函数,用法一致,都是采用映射原理

4.2.3 Mutations

1. mutations基本使用

  • 类型:{ [key: string]: Function }
  • 详细:
    • mutations里主要定义一些方法,用于修改Vuexstore状态(数据)
    • mutations中的内部方法会接受state 作为第一个参数,可以通过state.xxx获取store数据
    • 当其他组件想要修改修改Vuexstore状态(数据)
      • Vuex不允许在组件中直接调用this.$store.mutations.xxx()方式来修改store状态
      • 必须通过this.$store.commit('mutations下的方法名', 要传递的参数)来执行mutations下对应的方法修改数据
  • 示例:

 

    • 上图中methods下的return可以去掉

2. mutations其他提交方式

  • 提交mutations的另外一种风格
    • 除了this.$store.commit('xxx')可以提交mutations之外,Vuex还为我们提供了另外一种提交方式

 

    • 这种提交风格比较少用

3. mutations响应规则

  • 当我们使用mutations更新store中的数据时,必须遵守Vuex对应的一些规范
  • mutations更新数据规范
  1. 最好提前在你的 store --> state 中初始化好所有所需属性
  2. 当需要在对象上添加新属性时,应该使用Vue.set(obj, 'newProp', value)方式更新数据

 

 

4. mutations常量(了解)

  • 当mutations中方法过多时, 使用者需要花费大量的经历去记住这些方法名,甚至是多个文件间来回切换, 查看方法名称
  • Vuex允许我们可以创建一个文件: mutation-types.js,并且在其中定义mutations中方法名的常量,然后将其导出
  • 导入定义的常量时, 我们可以使用ES2015中的风格,使用一个常量来作为函数的名称
  • mutation-types.js
    • export const SOME_MUTATION = 'SOME_MUTATION'
  • store.js
    • import Vuex from 'vuex'
      import { SOME_MUTATION } from './mutation-types'

      const store = new Vuex.Store({
       
      state: { ... },
       
      mutations: {
         
      // 我们可以使用 ES2015 风格的命名功能来使用一个常量作为函数名
        [SOME_MUTATION] (state) {
           
      // ...
        }
      }
      })
  • App.vue
    • import * as type from './store/mutation-types'
      export default {
         
      methods: {
             
      add(number) {
                 
      this.$store.commit(type.SOME_MUTATION)
            }
        }
      }
  • Vuex官网说道:
    • 用不用常量取决于你
    • 但是在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。

5. mutations必须是同步函数

  • Vuex要求我们Mutation中的方法必须是同步方法.
    • 如果Mutations中的方式是一个异步操作,则在Vue devtools中将会无法记录到更新后的状态

 

  • 上图中你会发现state中的count数据一直没有被改变,因为vue devtools无法追踪到
  • So, 不要再mutation中进行异步的操作

4.2.4 Actions

1. actions的理解

  • Action 类似于 mutation,不同在于:
  • Action 提交的是 mutation而不是直接变更状态。Action 可以包含任意异步操作
  • 先回顾一下Vuex的状态管理图

 

  • Vuex不允许我们在mutations中进行异步操作,允许我们将异步相关操作写在actions
  • 但是!直接修改数据的操作还是要在mutations中定义,实际上actions中只是存放异步操作,并且在异步操作中通过commit方式提交mutations,完成异步操作数据的更新
  • 说起来有点难以理解,接下来我们看代码的展示!

2. actions的基本使用

  • 类型:{ [key: string]: Function }
  • 详细:
    • actions里主要定义一些方法,用于存放异步相关操作
    • actions中的内部方法会接受context 作为第一个参数。context是和store对象具有相同方法和属性的对象
      • 因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters
      • 当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了
    • 组件中可以通过this.$store.dispatch('actions下的方法名'),执行对应的actions方法
  • 示例:

 

3. actions传参

  • 组件在调用actions中的方法时,同样支持传递参数

 

4. 解构context形参

  • 我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit 很多次的时候):
    • actions: {
       
      adelay({ commit, getters, state }, payload) {
         
      setTimeout(() => {
           
      commit('delay', payload)
        },
      2000);
      }
      },

5. actions返回Promise

  • 当我们通过actions执行异步操作时,我们希望能够知道这个异步操作什么时候结束。
  • 首先,你需要明白 store.dispatch('xxx'),将会调用actions下的处理函数,因此我们可以让其处理函数返回一个Promise实例
  • 在Action中, 我们可以将异步操作放在一个Promise中, 并且调用对应的resolve或reject

 

4.2.5 Module (了解)

1. 认识Module

  • Vuex允许我们store分割成模块, 而每个模块拥有自己的state、mutations、actions、getters等
  • 每个模块拥有自己的局部状态(数据)。与store定义的全局状态(数据)不会冲突

 

2. 模块命名空间

  • 默认情况下,模块内部的 actionmutation getter 是注册在store下的
    • 这意味着模块内部的方法名与store中的方法名不能冲突
  • 你可以通过添加 namespaced: true 属性的方式使其成为带命名空间的模块。开启命名空间后,组件需要通过特定的语法去访问mutations、actions、以及getters
    • 组件访问模块的state:this.$store.模块.属性名
    • 组件访问模块的getters:this.$store.getters['模块名/属性名']
    • 组件提交模块的mutations:this.$store.commit('模块名/方法名')
    • 组件提交模块的actions:this.$store.dispatch('模块名/方法名')

 

3. 模块的局部状态

  • 对于模块内部的 mutations 和 getters,接收的第一个参数是模块的局部状态对象
  • 对于模块内部的 actions,局部状态通过 context.state 暴露出来,全局状态则为 context.rootState,对于模块内部的 getter,全局状态会作为第三个参数暴露出来
    • const moduleA = {
       
      actions: {
         
      add ({ state, commit, rootState }) {
         
      // 这里的state为局部状态,rootState为全局状态
             commit('increment')
        },
       
      getters: {
         
      moduleAbar(state, getters, rootState) {
             
      // 这里的 `state`是模块的局部状态 `rootState`是全局状态
             return state.name + 111
          }
        },
      }
      }

4.3 Vuex项目结构划分

  • Vuex的相关代码我们都是存放在store文件夹下的index.js中
  • 当index.js文件代码量太多时,只需将 actions、mutations 和 getters 分割到单独的JS文件。并用模块化导入到index.js中,这样的代码更好维护

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值