Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: {
... },
mutations: {
... },
actions: {
... },
getters: {
... }
}
const moduleB = {
state: {
... },
mutations: {
... },
actions: {
... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
在项目中一般都会将modules
模块根据业务需求分成多个js文件,每个js文件模块有各自的内容,如
modules
|__ user.js
|__ app.js
...
user.js
const user = {
state: {
...
},
mutations: {
...
},
actions: {
...
}
}
export default user
那么在创建store的时候就需要将这些模块文件一一导入,如果模块少这样写还可以接受,如果模块很多的情况下这样就不够优雅,那有没有方法可以将modules
下的模块动态加载进来呢。
import user from 'user.js'
import app from 'app.js'
...
const store = new Vuex.Store({
modules: {
user,
app,
....
});
最近接触到了一个函数require.context()
生成上下文模块,它包含对该目录中所有模块的引用。
用法:
接收三个参数
require.context(directory, useSubdirectories, regExp)
directory:需要检索的目录
useSubdirectories:是否检索子目录
regExp: 匹配文件的正则表达式,一般是文件名
返回参数
require.context()
返回一个require 函数,该函数接受一个参数。
该require函数有三个属性:resolve 、keys、id
- resolve: 是一个函数,他返回的是被解析模块的id 。
- keys: 也是一个函数,他返回的是一个数组,该数组是由所有可能被上下文模块解析的请求对象组成,也就是文件路径组成的数组。
- id:上下文模块的id。
require.context()
具体用法参考:// https://webpack.js.org/guides/dependency-management/#requirecontext
这里可以利用keys属性,获取到modules
文件夹下的所有js文件路径组成的数组,通过这个数组就可以拿到模块里的内容,最后将这些内容和文件名组成一个modules对象。
具体代码如下:
文件结构
store
|__modules
| |__ user.js
| |__ app.js
| |...
|__index.js
// 以下是index.js内容
import Vue from 'vue';
import Vuex from 'vuex';
import getters from './getters';
Vue.use(Vuex);
// 获取moudules文件下所有js文件
const context = require.context('./modules', false, /\.js$/);
// context.keys() 返回匹配成功模块的名字组成的数组
const modules = context.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1');
// 通过context(key)导出文件内容。在文件中时通过export.default导出的,所以后边加.default
const fileModule = context(modulePath);
modules[moduleName] = fileModule.default;
return modules;
}, {
});
const store = new Vuex.Store({
modules,
getters
});
export default store;