Vue 笔记 4 - vuex

Vue 笔记 4 - vuex

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

Github地址:https://github.com/vuejs/vuex

什么时候使用

  1. 多个组件依赖于统一状态
  2. 来自不同组件的行为需要变更同一状态

vuex 原理

  • Actions : 服务员
  • Mutations : 后厨
  • State : 菜肴

安装

1
2
npm i vuex
npm i vuex --save-bundle

搭建环境

  1. 创建文件: src/store/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 该文件用于创建Vuex中最为核心的store
import Vue from 'vue'

// 引入Vuex
import Vuex from 'vuex'
// 应用Vues
Vue.use(Vuex)

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

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

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

// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
  1. main.js中创建vm时传入store配置项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 引入Vue
import Vue from 'vue'
// 引入App
import App from './App.vue'
// 全局Mixin
// import {hunhe, mixin} from './mixin'

// 导入插件
// import plugins from './plugins'
// 引入vueResource
import vueResource from 'vue-resource'
// import Vuex from 'vuex'

// import store from './store/index' // index可以省略
import store from './store'

// 关闭Vue的生产提示
Vue.config.productionTip = false

// 应用插件
// Vue.use(plugins)
Vue.use(vueResource)

// 创建vm
new Vue({
el: '#app',
render: h => h(App),
store,
beforeCreate(){
Vue.prototype.$bus = this // 全局事件总线
}
})

getters

当state中的数据需要经过加工后再使用时,可以使用getters加工,
在store.js中追加getters配置:

1
2
3
4
5
6
7
8
9
10
const getters = {
bigSum(state){
return state.sum*10
}
}
// 创建并暴露store
export default new Vuex.Store({
// ...
getters
})

四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性:

    1
    2
    3
    4
    5
    6
    7
    computed: {
    // 第一种方式:借助mapState生成计算属性,从state中读取数据。(对象写法)
    ...mapState({he:'sum', xuexiao:'school', xueke:'subject'}),

    // 第二种方式:要求生成的计算属性名和state中的属性名一致。(数组写法)
    ...mapState(['sum', 'school', 'subject']),
    }
  2. mapGetters方法: 用于帮助我们映射getters中的数据为计算属性

    1
    2
    3
    4
    // 第一种方式:借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
    ...mapGetters({bigSum:'bigSum'}),
    // 第二种方式:要求生成的计算属性名和getters中的属性名一致。(数组写法)
    ...mapGetters(['bigSum'])
  3. mapActions方法: 用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    1
    2
    3
    4
    5
    6
    methods:{
    // 靠mapActions生成: incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd', incrementWait:'jiaWait'})
    // 靠mapActions生成: incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd', 'jiaWait'])
    }
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
    ...mapActions({incrementOdd: 'addOddAction', incrementWait: 'addWaitAction'})

    // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
    ...mapActions(['addOddAction', 'addWaitAction'])
    // 注意数组写法要求调用处需要修改为数组中生成的函数名:
    <button @click="addOddAction(n)">当前求和为奇数再加</button>
    <button @click="addWaitAction(n)">等一等再加</button>

备注:mapActions与mapMutations使用时,若需要传递参数,需要在模板中绑定事件时传递好参数,否则参数是事件对象。

模块化和命名空间

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

开启命名空间

修改:moduleA.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const moduleAOptions = {
namespaced:true, // 开启命名空间
actions: {
// ...
},
mutations: {
// ...
},
state: {
// ...
},
getters: {
// ...
}
}
export default moduleAOptions

moduleB.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default {
namespaced:true, // 开启命名空间
actions: {
// ...
},
mutations: {
// ...
},
state: {
// ...
},
getters: {
// ...
}
}

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vues
Vue.use(Vuex)

import moduleAOptions from './moduleA'
import moduleBOptions from './moduleB'

// 创建并暴露store
export default new Vuex.Store({
modules: {
moduleA: moduleAOptions,
moduleB: moduleBOptions
}
})

开启命名空间后,组件中读取state数据

1
2
3
4
5
6
// 方式1: 自己直接读取
this.$store.state.moduleA.list

// 方式2: 借助mapState读取
...mapState('moduleA',['state1','state2','state3'])

开启命名空间后,组件中读取getters数据

1
2
3
4
5
// 方式1: 自己直接读取
this.$store.getters['moduleA/personName']

// 方式2: 借助mapGetters读取
...mapGetters('moduleA',['getSum'])

开启命名空间后,组件中调用dispatch

1
2
3
4
5
// 方式1: 自己直接dispatch
this.$store.dispatch('moduleA/addPerson', person)

// 方式2: 借助mapActions取
...mapActions('countModule', {incrementOdd: "addOddAction",incrementWait: "addWaitAction"})

开启命名空间后,组件中调用commit

1
2
3
4
5
// 方式1: 自己直接commit
this.$store.commit('moduleA/addPersonMutation', person)

// 方式2: 借助mapMutations取
...mapMutations('moduleA',{ increment: "addMutation", decrement: "subMutation" }),