Vuex 的核心技术,需要记住的是编写 store 的顺序。案例简单,所以把 store 都写在了一个 index.js 文件中,这个对于小型的应用来说完全没有问题的。
很多企业级项目都是比较复杂的,如果把 store 逻辑都存放在一个 js 文件(想象一下一个 js 文件几千、上万行代码。。。),那维护起来可能会崩溃,比如说我们在网上买东西,这就至少涉及到了商品和购物车,如果这两个都写在一起,那么代码就很难阅读了,所以在 Vuex 中建议使用 Module 方案,也就是模块方案来维护 store.
配置 Vuex 模块
Vuex 模块简单来说就是把一个 store 文件分割成多个 js 文件,每个分割的文件就是一个模块,每个模块都拥有自己的 state、mutation、action、getter,甚至模块还可以嵌套子模块
多个模块在一个文件里
我们先看一下多个模块是怎么组合的,假定我们继续打开 store 目录下的 index.js 文件。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
Vuex.Store 里的 modules 属性可以添加多个子模块,如果我们想获取一个模块,你可以
store.state.a; // -> moduleA 的状态
store.state.b; // -> moduleB 的状态
分拆模块文件
如上面的配置,你也可以把每一个模块的对象存放在独立的一个文件中,我们推荐这样使用更好
我们改造一下之前的 count 例子
count.js
我们在 src/store 目录下创建 count.js
export default {
namespaced: true,
state: {
count: 0
},
actions: {
increment: ({ commit }) => commit("increment"),
decrement: ({ commit }) => commit("decrement")
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
}
};
这里额外介绍一下 namespaced: true 这个代表的是开启命名空间,这个设置的作用在于这个 module 的 state、mutation、action、getter 都限定在本 module 里,这样就不会污染别的 module,比如说两个 module 的 action 名称一样是没有关系的。我们一般都设置为 true。
集成 module
打开 src/store/index.js 文件,把刚才写的这个 count.js module store 导入进来
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
import count from "./count";
export default new Vuex.Store({
modules: {
count:count
}
});
需要注意的是 modules 对象里添加的属性名称就是 module 的名称哦,接下来会用到的
vue 中使用 module store
Vuex 提供了一个 createNamespacedHelpers 函数用来创建指定 namespace 的 module 引用,可以参看下面的代码。createNamespacedHelpers 接受的参数就是 module 的名称,上面我们提到过的
import { createNamespacedHelpers } from "vuex";
// 创建 count 模块的引用
const { mapState, mapActions } = createNamespacedHelpers("count");
export default {
computed: {
...mapState({
count: state => state.count
})
},
methods: { ...mapActions(["increment", "decrement"]) }
};
总结
上面的案例,我们使用的是一个 module,当然你也可以同样的方式添加多个 module。在引用的地方你如果想同时使用多个模块可以参考如下
const { mapState, mapActions } = createNamespacedHelpers("count");
const { mapState:demoMapState, mapActions:demoMapActions} = createNamespacedHelpers("demo");
export default {
computed: {
...mapState({
count: state => state.count
}),
...demoMapState({
demoCount: state => state.count
})
},
methods: { ...mapActions(["increment", "decrement"]) }
};
使用变量别名的方式就可以把两个module区分开了