Skip to content

使用Vuex

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

1. Vuex使用场景

  1. 多个组件依赖于同一状态
  2. 来自不同组件的行为需要变更同一状态 相对于全局总线,Vuex更适合不止2个组件的数据通信繁琐配置。

2. Vuex的工作原理

Alt text Actions并不多余,可以用来支持后代请求、校验等需求

3. 使用Vuex

Alt text

3.1 安装Vuex

sh
// 安装vuex
 npm i vuex@3

3.2 js文件配置

创建store文件夹,在store下面创建index.js文件

js
//  该文件用于创建Vuex中最为核心的store
import Vuex from "vuex"

// 准备actions-- 用于响应组件中的动作
const actions = {}

// 准备mutations---用于操作数据(state)
const mutations = {}

// 准备state--用于存储数据
const state = {}

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

// 暴露store,可以简写直接export上面store
export default store
js
// 引入vue
import Vue from 'vue'
import Vuex from "vuex"
// 引入App组件,它是所有组件的父组件
import App from './App.vue'
// 关闭vue的生产提示
Vue.config.productionTip = false

// 可以不写index.js, 注意使用简写如果没有index.js就会报错
import store from "@/store";

Vue.use(Vuex)

// 创建vm实例对象
new Vue({
  // 将App组件放到容器中
  render: q => q(App),
  store,
  beforeCreate() {
    Vue.prototype.$bus = this
  }
}).$mount('#app')

运行发现报错: Alt text 按照报错提示需要先Vue.use(Vuex)再创建store实例对象,如果简单的调换第10行和12行代码,问题依旧,原因在于es6中import的执行优先其他代码执行,也就是执行的时候会扫描import语句,将所有import语句汇总到一起优先执行,在执行后面的其他语句。
解决办法:将Vue.use(Vuex)移动到index.js中去。

js
//  该文件用于创建Vuex中最为核心的store
import Vuex from "vuex"

// 准备actions-- 用于响应组件中的动作
const actions = {}

// 准备mutations---用于操作数据(state)
const mutations = {}

// 准备state--用于存储数据
const state = {}

Vue.use(Vuex)
// 创建store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

页面不再报错,vm实例出现$store属性信息: Alt text

编写index.js中actions, mutations

js
//  该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
import Vuex from "vuex"

// 准备actions-- 用于响应组件中的动作
const actions = {
    // 没有处理逻辑,可以直接commit
   /* 'jia': function (context, num){
        context.commit('JIA', num)
    },
    'jian': function (context, num){
        context.commit('JIAN', num)
    },*/
    jiaSumOdd(context, num) {
        if (context.state.sum % 2 == 1) {
            context.commit('JIA_SUM_ODD', num)
        }
    }
}

// 准备mutations---用于操作数据(state)
const mutations = {
    'JIA': function (state, num){
        state.sum += num
    },
    'JIAN': function (state, num){
        state.sum -= num
    },
    JIA_SUM_ODD(state, num) {
       state.sum += num
    }
}

// 准备state--用于存储数据
const state = {
    sum: 0
}

Vue.use(Vuex)

// 创建store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

打开开发者工具: Alt text

  • 不建议把所有逻辑代码都写到actions里面,因为开发者工具监测不到, 也不建议逻辑代码都写到组件里面,使用commit到mutations, 如果逻辑非常复杂代码很多,这样组件不能代码复用
  • 组件中读取vuex中的数据: $store.state.sum
  • 组件中修改vuex中的数据: $store.dispatch('actions中的方法名',数据)或者$store.commit('mutations中的方法名', 数据)

提示

若没有网络请求或者其他业务逻辑,组件中可以越过actionss,即不写dispatch, 直接编写commit

4. getters配置

如果涉及到vuex中的数据需要计算才能展示数据:

  1. 可以直接在组件中使用插值语法 Alt text
  2. 可以在组件中使用计算属性 Alt text
  3. 可以使用getters配置
  • 概念: 当state中的数据需要经过加工后再使用时, 可以使用getters加工。
  • 在store.js中追加getters配置
js
const getters = {
    bigSum(state){
        return state.sum * 10
    }
}
Vue.use(Vuex)
// 创建store
export default new Vuex.Store({
    ......
    getters
})
  • 组件中读取数据: $store.getters.bigSum

5. 使用mapState和mapGetters简化读取Vuex数据

如果不使用mapState和mapGetters, 那可以使用computed属性, 不过编码需要写不少代码 mapState方法:用于帮助我们映射state中的数据为计算属性 mapGetters方法:用于帮助我们映射getters中的数据为计算属性 Alt text

5.1 引入mapState,mapGetters函数

js
import {mapState, mapGetters} from "vuex";

5.2 查看使用mapState帮我们生成的函数

js
mounted() {
  const x = mapState({he: 'sum'})
  console.log(x)
}

Alt text 可以看到生成一个名字叫mappedState的函数, 名字不需要关心也用不到,它对应的属性是he,我们用he即可调用到mappedState函数 将mapState帮我们生成的函数加到computed中

js
computed:{
  // 借助mapState生成计算属性,从state中读取数据。(对象写法)
  // ...mapState({he: 'sum'})
  // 数组写法
  ...mapState(['sum']),
  // 借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
  ...mapGetters(["bigSum"])
},

Alt text

5.3 mapActions和mapMutations

使用mapActions和mapMutations方法简化dispatch和commit mapActions方法: 用于帮助我们生成与actions对话的方法, 即包含$store.dispatch(xxx)的函数 Alt text mapMutations方法: 用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)函数 Alt text