在日常引入组件,模块的时候,其实目录格式都差不多,能不能一键引入所有呢?require.context 可以帮助我们实现这个功能。需要 webpack (或在内部使用了 webpack 的 Vue CLI 3+)
传统引入,如果文件有很多,就会很麻烦,而且后期每加一个文件,需要再导入一次
import moduleA from './modules/moduleA.vue'
import moduleB from './modules/moduleB.vue'
import moduleC from './modules/moduleC.vue'
export default {
components: {
moduleA,
moduleB,
moduleC
}
}
接下来文章会介绍利用require.context
,实现自动导入模块供能,解放我们的双手。
首先先介绍一下 require.context
~
require.context是什么
一个webpack的api, 通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块
require.context 方法
require.context
函数接受三个参数
-
directory
{String} - 要搜索的目录 -
useSubdirectories
{Boolean} - 是否还搜索其子目录 -
regExp
{RegExp} - 匹配文件的正则表达式
语法如下:
require.context(
directory,
(useSubdirectories = true),
(regExp = /^\.\/.*$/),
(mode = 'sync')
);
借用 webpack
官网例子
require.context("./test", false, /\.test\.js$/);
// 遍历当前目录下的test文件夹下的所有以 ‘.test.js’ 结尾的文件,不遍历子目录
require.context("../", true, /\.stories\.js$/);
// 遍历当前目录下的所有 以 '.stories.js' 结尾的文件,且会遍历子目录
注:传递给 require.context
的参数必须是字面量(literal)
require.context 方法的返回
require.context
函数执行后返回的一个 require 函数,此函数接受一个参数:request
- 小编理解:对
require
函数的使用,例如:传入 test 文件夹下面匹配文件的相对路径,得到其返回的esmodule
- 注:这里
test
文件夹是指require.context
函数的第一个参数值,这里传入的是test,所以传入的是 test 文件夹下面匹配文件的相对路径
此函数有 3 个属性
-
resolve
{Function}- 官方:接受一个参数
request
,它返回 request 被解析后得到的模块id
- 小编理解:传入 test 文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径
- 官方:接受一个参数
-
keys
{Function}- 官方:它返回一个数组,由所有可能被此
context module
处理的请求组成。 - 小编理解:返回匹配成功模块的名字组成的数组
- 官方:它返回一个数组,由所有可能被此
-
id
{String}- 官方:是
context module
的模块id
. 它可能在你使用module.hot.accept
时会用到
- 官方:是
结合工程输出查看属性返回值
这里只贴出部分代码,具体工程实例下面有展示:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const context = require.context('./modules', true, /\.js$/)
console.log('----------- context ---------')
console.log(context)
console.log('----------- contex.id ---------')
console.log(context.id)
console.log('----------- context.resolve---------')
console.log(context.resolve)
console.log('----------- context.resolve(./moduleA.js) ---------------')
console.log(context.resolve('./moduleA.js'))
console.log('----------- context.keys() ---------')
console.log(context.keys())
const modules = context.keys().reduce((modules, modulePath) => {
// set './moduleA.js' => 'moduleA'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
console.log(`----------- context(${modulePath}) ------------`)
const value = context(modulePath)
console.log(value)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
查看控制台输出:
工程化实例
自动化导入组件
目录
核心代码
// App.vue
<template>
<div id="app">
<my-header></my-header>
<my-main></my-main>
<my-footer></my-footer>
</div>
</template>
<script>
// 关键代码
const modulesFiles = require.context('./components', true, /\.vue$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './myHeader.js' => 'myHeader'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
export default {
name: 'App',
// 关键代码
components: modules
}
</script>
自动化导入 vuex 模块
目录
核心代码
// store/modules/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const context = require.context('./modules', true, /\.js$/)
const modules = context.keys().reduce((modules, modulePath) => {
// set './moduleA.js' => 'moduleA'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = context(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
项目代码
这里有自动化导入模块的完整代码,欢迎fork、star,有问题可以提 issue
最后
通过require.context
可以自动化引入文件,不单单局限于组件、vuex, 所有模块文件都是通用的, 例如路由, 接口封装模块,都是可以使用的。
如果上文有错误希望大家多多指出