简述Vuex的使用

374 阅读3分钟

前言

这是我从事程序员这个职业以来发表的第一篇技术博客,其实这是我一直想做的事情,但是迟迟没有行动,今天终于开始了,写博客是一件双赢的事情,既巩固自己所学,又可以帮助他人,我相信自己会一直写下去,如有不对的地方也希望各位大佬多多指正。好了,下面开始进入正题。

Vuex理解

Vuex 是一个专为 Vue.js 应用程序开发的状态管理库,适用于多个组件共享状态的情况,Vuex起到了一个对组件状态进行集中式管理的作用。

Vuex的主要组成部分

我们一般会在src目录下创建一个store(或者vuex)文件夹,用来存放Vuex的几个组成模块,分别是:state、actions、mutation-types、mutations、getters、index。

State

state就是Vuex管理的状态对象,将所有需要共享的数据包裹在一个对象中暴露出去

state.js

/*
vuex管理的状态对象
*/
export default {
  address:{}, // 地址信息对象
  categorys:[], // 商品种类
  shops:[], // 商铺列表
  user:{}, // 登录的用户信息
}

下面就涉及到一个问题,组件中如何读取Vuex中的state状态呢?

  1. 首先在main.js中注册store选项,该 store 实例会注入到根组件下的所有子组件中,然后在子组件中就可以通过 this.$store.store.状态名 获取到Vuex中的状态数据
  2. 通过mapState辅助函数来读取,这种写法比较精炼,适用读取多个状态。 image.png

Actions

actions包含多个事件回调函数的对象,通过执行commit()来触发mutation的调用,间接更新状态(不直接更新状态的原因是mutation必须同步执行),可以包含异步代码(定时器、ajax请求等),action函数接收2个参数:({commit, state}, data)。 组件中分发action的2种方式:

  1. 通过 $store.dispatch('action名称',data) 的方式来分发action。
  2. 使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store
import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}
actions.js  异步action

// 异步获取食品分类列表
async getCategorys({commit}) {
  const result = await reqCategorys()
  if(result.code === 0){
    const categorys = result.data
    commit(RECEIVE_CATEGORYS,{categorys})
  }
}
actions.js 同步action

// 同步保存用户信息
saveUser({commit},user){
  commit(SAVE_USER,{user})
},

Mutations

mutations包含多个直接更新state的方法的对象,由action中的commit()触发调用,mutation接收2个参数,state和commit函数传递过来的对象数据,mutation必须是同步函数。

mutations.js

[RECEIVE_ADDRESS](state,{address}){
  state.address = address
},

[RECEIVE_CATEGORYS](state,{categorys}) {
  state.categorys = categorys
},

Mutation-types

mutation事件类型的常量名称模块。使用常量名称模块主要有以下2个好处:

  1. 常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然
  2. actions和mutations中用到的事件类型直接引入常量名称模块,这样不至于写错

Getters

包含多个基于state的getter计算属性的对象,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,getter接受 state 作为其第一个参数。 三种组件中访问方式:

  1. 通过属性访问
getters.js

// 购物车商品总数量
totalCount (state) {
  return state.shopCart.reduce((pre,food) => pre + food.count,0)
},
  1. 通过方法访问 可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
getters.js

getters: {
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}

store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
  1. mapGetters辅助函数

image.png

Module

当应用程序的功能模块比较多时,所有的状态都集中到一个对象,这样store对象就变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

Index

Vuex的核心管理对象store对象模块,将Vuex的各组成部分引入,并声明Vue使用上Vuex

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'

Vue.use(Vuex)
export default new Vuex.Store({
  state,
  actions,
  mutations,
  getters
})

Vuex与组件交互流程图

Vuex流程
图.png