Vuex

  1. 概念:

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

  2. 使用场景:共享数据

    1. 多个组件依赖同一状态
    2. 来自不同组件的行为需要变更同一状态
  3. 原理图:

    image-20220417110641002

    vuex由三个部分组成:Actions、Mutations、State,并统一由store来管理

    Actions:接收Vue Components 对共享数据的操作并commit给Mutations(还有一个很重要的作用是可以只接收操作,但是数据可以在Actions中向后端请求或者有一定的业务逻辑)

    Mutations:按照Actions提交的操作对共享数据进行相应具体的操作(同样允许Vue Components直接调用commit越过Mutations)

    State:存储共享数据

基本使用

  • 安装vuex:npm i vuex (如果是vue2 只能安装npm i vuex@3)

  • 创建store来管理vuex的三个主要对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //在main.js中引入store 因为js名叫index所以可以省略
    import store from './store'

    //创建vm
    new Vue({
    el:'#app',
    render: h => h(App),
    store,
    beforeCreate() {
    Vue.prototype.$bus = this
    }
    })
  • 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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    //该文件用于创建Vuex中最为核心的store
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex插件
    Vue.use(Vuex)

    //准备actions——用于响应组件中的动作,可以用于异步操作
    const actions = {
    add(context,value){
    console.log('actions中的add被调用了')
    context.commit('ADD',value)
    },
    sub(context,value){
    console.log('actions中的sub被调用了')
    context.commit('SUB',value)
    },
    addOdd(context,value){
    console.log('actions中的addOdd被调用了')
    if(context.state.sum % 2){
    context.commit('ADD',value)
    }
    },
    addWait(context,value){
    console.log('actions中的addWait被调用了')
    setTimeout(()=>{
    context.commit('ADD',value)
    },500)
    }
    }
    //准备mutations——用于操作数据(state)并且必须是同步方法
    const mutations = {
    ADD(state,value){
    console.log('mutations中的ADD被调用了')
    state.sum += value
    },
    SUB(state,value){
    console.log('mutations中的SUB被调用了')
    state.sum -= value
    }
    }
    //准备state——用于存储数据
    const state = {
    sum:0 //当前的和
    }

    //准备getters——用于将state中的数据进行加工
    const getters = {
    bigSum(state){
    return state.sum*10
    }
    //可以直接获取getters的数据再加工
    bigSum2(state,getters){
    return getters.bigSum*10
    }
    //可以通过函数获取组件调用getters传来的参数
    bigSum3(state){
    return num => {
    return state.sum*num
    }
    }
    }

    //创建并暴露store
    export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
    })
  • 使用vuex:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <h1>当前求和为:{{$store.state.sum}}</h1>
    <h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>
    methods: {
    increment(){
    this.$store.commit('ADD',this.n)
    },
    decrement(){
    this.$store.commit('SUB',this.n)
    },
    incrementOdd(){
    this.$store.dispatch('addOdd',this.n)
    },
    incrementWait(){
    this.$store.dispatch('addWait',this.n)
    },
    },

    mapState、mapGetters、mapActions、mapMutaions

    作用:自动生成相关属性,用于简化模板语法

    用法:写在各个组件的计算属性中

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

    //借助mapState生成计算属性,从state中读取数据。(数组写法,但必须与属性名一致)
    ...mapState(['sum','school','subject']),
    • mapGetters
    1
    2
    3
    4
    5
    //借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
    ...mapGetters({bigSum:'bigSum'})

    //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
    ...mapGetters(['bigSum'])
    • mapActions(注意使用方法时需要带相应的参数)
    1
    2
    3
    4
    5
    //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

    //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
    ...mapActions(['jiaOdd','jiaWait'])
    • mapMutations(注意使用方法时需要带相应的参数)
    1
    2
    3
    4
    5
    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),

    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
    ...mapMutations(['JIA','JIAN']),

    模块化

Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.当应用变得非常复杂时,store对象就有可能变得相当臃肿.为了解决这个问题, Vuex允许我们将store分割成模块(Module),而每个模块拥有自己的state、mutations、actions、getters等

  1. 模块化的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const moduleA = {
state:{...},
mutations:{...},
actions:{...},
getters:{...}
}
const moduleB = {
state:{...},
mutations:{...},
actions:{...},
getters:{...}
}

const store = new Vuex.Store({
modules:{
a:moduleA,
b:moduleB
}
})
  1. 模块化使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//获取模块中的state
//1.直接获取
this.$store.state.a.属性名
//2.用mapstate,但是必须给每个模块配置namespaced:true
...mapState('a',['sum','school','subject'])
//获取模块中的getters
//1.直接获取
this.$store.getters['a/bigSum']
//2.mapGetters,但是必须给每个模块配置namespaced:true
...mapGetters('a',['bigSum'])
//获取模块中的actions
//1.直接获取
this.$store.dispatch('模块名/addOdd',this.n)
//2.mapActions,但是必须给每个模块配置namespaced:true
...mapActions('a',['jiaOdd','jiaWait'])
//获取模块中的mutations
//1.直接获取
this.$store.commit('模块名/ADD',this.n)
//2.mapMutations,但是必须给每个模块配置namespaced:true
...mapMutations('a',['JIA','JIAN'])