Vuex

78 阅读4分钟

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

直白点说就是多个组件需要对同一个数据进行变更时可以使用vuex,更方便一些。

下图是vuex的工作模式。

微信图片_20230815160032.png

配置vuex环境

安装vuex npm i vuex@3 vue2使用vuex3

然后创建一个src/store/index.js文件

// 引入Vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)

// 准备actions 用于响应组件动作
const actions = {}
// 准备mutations 用于操作数据(state)
const mutations = {}
// 准备state 用于存储数据
const state = {}

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

main.js文件中引入index.js文件,配置store。

import Vue from 'vue'
import App from './App'
// 引入index.js文件
import store from './store/index.js'
// 关闭生产提示
Vue.config.productionTip = false;
// 创建Vue实例
new Vue({
    el: '#app',
    render: h => h(App),
    store
})

基本使用

初始化数据、配置actionsmutations,操作文件stroe.js

// 创建Store
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
// 应用插件
Vue.use(Vuex);
// 创建actions 用于响应组件中的动作
const actions = {
    addOdd(content, value){
        if(content.state.sum % 2){
            content.commit('ADDODD', value);
        }
    },
    addWait(content, value){
        setTimeout(()=>{
            content.commit('ADDWAIT', value);
        }, 1000)
    }
};
// 创建mutations 用于操作数据
const mutations = {
    ADD(state, value){
        state.sum += value;
    },
    MIN(state, value){
        state.sum -= value;
    },
    ADDODD(state, value){
        state.sum += value;
    },
    ADDWAIT(state, value){
        state.sum += value;
    }
};
// 创建state 用于存储数据
const state = {
    sum: 0
};

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

getters的使用

state中的数据需要经过加工后再使用时,可以使用getters配置项进行加工。

store/index.js文件中添加getters配置。

......

// 创建getters 用于将state中的数据进行加工
const getters = {
    bigSum(state){
        return state.sum * 10;
    }
}

// 创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
});    

组件中通过$store.getters读取数据。

<h1>当前求和放大10倍:{{ $store.getters.bigSum }}</h1>

四个map方法的使用

使用vuex展示数据时,前缀过长,所以我们可以通过计算属性获得state中的数据。

computed: {
    sum(){
        return this.$store.state.sum;
    },
    bigSum(){
        return this.$store.getters.bigSum;
    },
    school(){
       return this.$store.state.school;
    },
    subject(){
        return this.$store.state.subject;
    }

},

但是上述传统方法会使得代码冗余,重复代码较多,所以我们可以通过vuex提供的四个map方法帮助我们更好的获得数据,注意要先引入这些方法。

    import {mapState, mapGetters, mapActions, mapMutations} from 'vuex';

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

computed: {
    // 借助mapState方法生成计算属性(对象写法)
    ...mapState({sum: 'sum', school: 'school', subject: 'subject'})

    // 借助mapState方法生成计算属性(数组写法),仅限于属性名和state中的数据名相同
    ...mapState(['sum', 'school', 'subject'])

},

mapGetters()方法 用于帮助我们映射getters中的数据为计算属性

computed: {
    // 借助mapGetters方法生成计算属性(对象写法)
    ...mapGetters({bigSum: 'bigSum'})

    // 借助mapGetters方法生成计算属性(数组写法),仅限于属性名和state中的数据名相同
    ...mapGetters([bigSum])

},

mapActions()方法 用于帮助我们生成与actions对话的方法,包含$store.dispatch(xxx)的函数。

computed: {
    // 借助mapActions方法生成计算属性(对象写法)
    ...mapActions({incrementOdd: 'addOdd', incrementWait: 'addWait'}),

    // 借助mapActions方法生成计算属性(数组写法),仅限于方法名和actions中的方法名相同。
    ...

},

mapMutations()方法 用于帮助我们生成与mutations对话的方法,包含$store.commit(xxx)的函数。

computed: {
    // (对象写法)
    ...mapMutations({increment: 'ADD', decrement: 'MIN'}),
    // (数组写法)
    ...
},

注意:mapActions()mapMutations()方法生成的函数,如果需要传递参数,在模板中绑定事件时就要传递,否则默认参数是事件对象Event。

<button @click="decrement(n)">-</button>
<button @click="increment(n)">+</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>

vuex模块化

vuex模块化是为了让代码更好维护,让多种数据分类更加明确。

新建一个./store/count.js文件用于配置求和组件使用到的数据,注意要配置namesspaced属性,用于开启命名空间。

export default  {
    namespaced: true,
    state: {
        sum: 0,
        school: '尚硅谷',
        subject: '前端',
    },
    getters: {
        bigSum(state){
            return state.sum * 10;
        }
    },
    actions: {
        addOdd(content, value){
            if(content.state.sum % 2){
                content.commit('ADDODD', value);
            }
        },
        addWait(content, value){
            setTimeout(()=>{
                content.commit('ADDWAIT', value);
            }, 1000)
        }
    },
    mutations: {
        ADD(state, value){
            console.log(value);
            state.sum += value;
        },
        MIN(state, value){
            state.sum -= value;
        },
        ADDODD(state, value){
            state.sum += value;
        },
        ADDWAIT(state, value){
            state.sum += value;
        },
    }
}

./store/index.js文件中引入count.js模块,并且在暴露store时要使用modules属性配置模块,就像是父组件使用components配置子组件一样。

// 创建Store
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
import countOptions from './count';
// 应用插件
Vue.use(Vuex);

// 创建并暴露store
export default new Vuex.Store({
    // 配置模块
    modules: {
        countOptions
    }
});

开启命名空间后读取数据或者调用dispatch、commit时与之前是有一些区别的。、

  • 读取state数据。
// 方式一:自己直接读取
this.$store.state.countOptions.sum
// 方式二:借助mapState读取
...mapState('countOptions',['sum', 'school', 'subject']),
  • 读取getters数据。
// 方式一:自己直接读取
this.$store.getters['countOptions/bigSum]
// 方式二:借助mapGetters读取
...mapGetters('countOptions', ['bigSum']),
  • 调用dispatch
// 方式一:自己直接调用dispatch
this.$store.dispatch('countOptions/addPersonWang', this.n);
// 方式二:借助mapActions读取
...mapActions('countOptions',{incrementOdd: 'addOdd', incrementWait: 'addWait'}),
  • 调用commit
// 方式一:自己直接调用commit
increment(){
    return this.$store.commit('countOptions/ADD', this.n);
}
// 方式二:借助mapMutations读取
...mapMutations('countOptions', {increment: 'ADD', decrement: 'MIN'})