# vuex

# 1. 介绍

在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

# 2. 与全局事件总线的对比

全局事件总线(多组件共享数据):

全局事件总线(多组件共享数据)

vuex(多组件共享数据):

vuex(多组件共享数据)

# 3. 何时使用?

多个组件需要共享数据时:

  • 多个组件需要读取同一个数据
  • 多个组件需要修改同一个数据

# 4. 原理图

https://v3.vuex.vuejs.org/vuex.png

# 5. 搭建 vuex 环境

# 5.1. 安装

# vue2.x 使用 vuex3
npm i vuex@3

# 5.2. 准备 store 对象

store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'

// 创建 Vuex.Store 实例之前,必须先 Vue.use(Vuex)
Vue.use(Vuex); 

// 准备 actions 对象 —— 响应组件中用户的动作
const actions = {}
// 准备 mutations 对象 —— 修改 state 中的数据
const mutations = {}
// 准备 state 对象 —— 保存具体的数据
const state = {}

// 创建 store
const store = new Vuex.Store({
  actions,
  mutations,
  state
});

// 暴露 store
export default store;

注意:

  • 创建 Vuex.Store 实例之前,必须先 Vue.use(Vuex)
  • webpack 优先执行 import xxx 语句,也就是说 import 语句会置顶执行

# 5.3. 注册

main.js:

import Vue from 'vue';
import store from './store';

// Vue.use(vuex) 之后,所有的 vm、vc 都有 $store 属性
// 给当前 vm.options.store 赋值 store 后,
// 当前 vm 及其管理的所有 vc 都能通过 $store 访问到 store 

new Vue({
  // ...
  store,
});

# 6. 基本使用

store = {
  state: {
    sum: 0
  },
  actions: {
    // context = { dispatch commit getters state rootGetters rootState }
    // 注意:
    //  actions 中一定要调用 commit 对 state 进行更改,
    //  因为 devtools 是跟 mutations 打交道的
    addWhenOdd({ state, commit }, param) {
      if (state.sum % 2 === 1) {
        commit('ADD', param);
      }
    }
  },
  mutations: {
    ADD(state, param) {
      state.sum += param;
    }
  }
}

# 6.1. 读

this.$store.state.xxx

# 6.2. 写

this.$store.dispatch('add', 2);

// 若没有网络请求或其他业务逻辑,组件中也可以越过 actions,而直接调用 mutations
this.$store.commit('ADD', 2);

# 7. getters

# 7.1. 概念

当 state 中的数据需要经过加工后再使用时,可以使用 getters 加工。

state 与 getters,可以类比 data 和 computed

# 7.2. 配置

store = {
  state: {
    sum: 0,
  },
  getters: {
    bigSum(state) {
      return state.sum * 10;
    }
  }
}

# 7.3. 读取

this.$store.getters.bigSum;

# 8. 四个 map 方法的使用

# 8.1. mapState

用于把 state 映射为 计算属性

mapState 的返回值是对象:

mapState({ mySum: 'sum', myStudentName: 'studentName' });

/*
{
  myStudentName: ƒ mappedState()
  mySum: ƒ mappedState()
}
*/

示例:

import { mapState } from 'vuex';

options = {
  computed: {
    // 繁琐写法
    sum() {
      return this.$store.state.sum;
    },
    
    // 数组写法: sum => this.$store.state.sum
    ...mapState([ 'sum', /* ... */ ]),

    // 对象写法: sum => this.$store.state.sum
    ...mapState({ sum: 'sum', /* ... */ }),

    // 对象写法: mySum => this.$store.state.sum
    ...mapState({ mySum: 'sum' }),

  },
}

# 8.2. mapGetters

用于把 getters 映射为 计算属性

import { mapGetters } from 'vuex';

options = {
  computed: {
    bigSum() {
      return this.$store.getters.bigSum;
    },

    ...mapGetters([ 'bigSum' ]),

    ...mapGetters({ myBigSum: 'bigSum' }),
  },
}

# 8.3. mapMutations

用于把 mutations 映射为 方法

注意:方法的第一个参数会当成 payload 传递过去

import { mapMutations } from 'vuex';

options = {
  methods: {
    add(num) {
      this.$store.commit('ADD', num);
    },

    // 数组写法: ADD(num) => this.$store.commit('ADD', num);
    ...mapMutations(['ADD']),

    // 对象写法: add(num) => this.$store.commit('ADD', num);
    ...mapMutations({ add: 'ADD' }),
  },
}

# 8.4. mapActions

用于把 actions 映射为 方法

注意:方法的第一个参数会当成 payload 传递过去

import { mapActions } from 'vuex';

options = {
  methods: {
    addWhenOdd(num) {
      this.$store.dispatch('addWhenOdd', num);
    },

    // 数组写法: addWhenOdd(num) => this.$store.dispatch('addWhenOdd', num);
    ...mapMutations(['addWhenOdd']),

    // 对象写法: addWhenOdd(num) => this.$store.dispatch('addWhenOdd', num);
    ...mapMutations({ addWhenOdd: 'addWhenOdd' }),
}

# 9. modules

# 9.1. 目的

让代码更好维护,让多种数据分类更加明确。

# 9.2. 配置

修改store.js

const countAbout = {
  namespaced: true,//开启命名空间
  state:{ x: 1 },
  mutations: { ... },
  actions: { ... },
  getters: {
    bigSum(state){
      return state.sum * 10
    }
  }
}

const personAbout = {
  namespaced: true, //开启命名空间
  state:{ ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    countAbout,
    personAbout
  }
})

# 9.3. 读取 state 数据

// 方式一:自己直接读取
this.$store.state.personAbout.list

// 方式二:借助 mapState 读取:
...mapState('countAbout',['sum','school','subject']),

# 9.4. 读取 getters 数据

// 方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']

// 方式二:借助 mapGetters 读取:
...mapGetters('countAbout',['bigSum'])

# 9.5. 调用 dispatch

//方式一:自己直接 dispatch
this.$store.dispatch('personAbout/addPersonWang', person)

//方式二:借助mapActions:
...mapActions('countAbout', { incrementOdd: 'jiaOdd', incrementWait: 'jiaWait' })

# 9.6. 调用 commit

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON', person)

//方式二:借助mapMutations:
...mapMutations('countAbout', { increment:'JIA',decrement:'JIAN' })
本章目录