Vue2全家桶 - VueX - 【2】模块化【模块化基本语法、state、mutations、actions、getters】

74 阅读2分钟

一、模块化基本语法

  • 在对应的模块中写

1.1 方式一

const Module = {
    /**
     * 没有启用命名空间的时候,mutations是注册到全局的
     * 启用命名空间以后,mutations只注册到当前模块下
     * 
     */
    // 启用命名空间
    namespaced: true
    // 和没有模块化的不一样
    // 模块化的state是一个函数(可以是箭头函数)
    state(){
        return {}
    },
    mutations: {},
    actions: {},
    getters: {}
}

/**
 * 默认导出
 * 导出模块,目的是为了在其他文件中能够导入
 * 如果有import,那么一定会有export
 */
export default Module

1.2 ✅ 方式二

  • 我自己喜欢这种方式,比较简单;
const start = {
    // 存储数据
}

const mutations = {
    // 同步修改 state 的方法 或 其他逻辑
}

const actions = {
    // 异步修改 state 的方法 或 其他逻辑
}

export default {
    // 开启命名空间
    namespaced: true,
    state,
    mutations,
    actions
}

二、state

  • 需要从模块去映射,需要使用对象作为入参,使用key,value的形式;
// 计算属性
computed: {
    ...mapState({
        /**
         * 这里需要从模块去映射,需要使用对象作为入参,使用key,value的形式
         * 新的变量名: (state) => state.模块名.该模块中对应的变量名
         * XianCount: (state) => state.Xian.count
         * ChengduCount: (state) => state.Chengdu.count,
         */
        // 解构 state
        XianCount: ({ Xian }) => Xian.count,
        ChengduCount: ({ Chengdu }) => Chengdu.count,
    }),
},

三、mutations

  • 没有模块化之前,mutations 是 注册到 全局的;
  • 模块化之后,要实现每个模块的独立,需要使用命名空间(namespaced: true)
  • 注意
    • 解构 mapMutations 的时候,需要写 对应的 mutations 属于 哪个模块
methods: {
    // ❌ 原样映射
    // ...mapMutations(["Xian/updateCount", "Chengdu/updateCount"]),
    
    // ✅ 别名映射
    ...mapMutations({
        // 新的方法名: '模块名/该模块中对应的方法名',
        updateXianCount: "Xian/updateCount",
        updateChengduCount: "Chengdu/updateCount",
    }),
    // 同步修改
    doDeliver(city, changedValue) {
        if (city === "xian") {
            /**
            * 模块化 mutations 的 原始写法
            * this.$store.commit("Xian/updateCount", changedValue);
            */

            // 原样映射 - 太丑太难看
            // this["Xian/updateCount"](changedValue);

            //别名映射
            this.updateXianCount(changedValue);
        } else {
            /**
            * 模块化 mutations 的 原始写法
            * this.$store.commit("Chengdu/updateCount", changedValue);
            */

            // 原样映射
            // this["Chengdu/updateCount"](changedValue);

            //别名映射
            this.updateChengduCount(changedValue);
        }
    }
},

四、 actions

  • 注意
    • 解构 mapActions 的时候,需要写 对应的 actions 属于 哪个 模块
methods: {
    // 异步修改
    ...mapActions({
        // 新的变量名: '模块名/模块名中对应的方法名',
        XianDeliver: "Xian/deliver",
        ChengduDeliver: "Chengdu/deliver",
    }),
    
    deliver(city, changedValue) {
        if (city === "xian") {
            /**
            * actions原始写法
            * this.$store.dispatch("Xian/deliver", changedValue);
            */

            // 原样映射
            this.XianDeliver(changedValue);
        } else {
            /**
            * actions原始写法
            * this.$store.dispatch("Chengdu/deliver", changedValue);
            */

            // 原样映射
            this.ChengduDeliver(changedValue);
        }
    }
}

五、 getters

  • getters: 由于是对 不同模块state 进行运算,所以要定义在 根store实例 中;

5.1 ✅ 方式一

  • 这种方式更简单,更实用;
  • @/store/getters.js
const getters = {
    变量名: (state) => state.模块名.变量名,
    变量名: ({ 模块名 }) => 模块名.变量名,
    函数名(state, payload) {
        return 相关逻辑
    }
}
export default getters

5.2 方式二

  • 这种方式也要会;
  • store/index.js
import Vue from "vue";

// 1.导入 vuex
import Vuex from 'vuex'

// 1.2 导出 Xian 和 Chengdu 两个模块
import XianModule from '@/store/module/Xian'
import ChengduModule from '@/store/module/Chengdu'

import getters from '@/store/getters.js'

// 2.注册 Vuex
Vue.use(Vuex)

// 3.实例化 Vuex.Store 对象
const store = new Vuex.Store({
    state: {},
    mutations: {},
    actions: {},
    getters
})

// 4.默认导出
export default store