require.context命令的使用 require.context基本使用
相信大家在项目中一定会经常看到require.context,懂行的朋友应该都知道这个api的作用:将某个文件夹的内容全部导入进来。所以它的应用场景也很明显:比如:1.用于全局组件的导入 2.引入vuex的module 3.svg图片的引入 4.其他需要同一文件夹多个导入的场景
那么,它究竟是怎么工作的呢?
一、下面以全局组件的导入作为例子
1.require.context接收三个参数,分别是1:directory {String} -要搜索的目录路径,:2:标记表示是否还搜索其子目录(Boolean), :3:匹配文件的正则表达式
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/\.vue$/
)
console.log(requireComponent)
上面的代码遍历./components文件夹下的所有.vue.js结尾的文件,不遍历子目录,可以看到这里的files是返回了一个函数,此函数可以接收一个参数:request ,把这个参数传进去就可以拿到我们导入的组件。那么这个参数从哪里来呢? 这个参数就是keys ()函数返回的数组中的每一项,那keys函数从哪里来?
再介绍一下,返回的这个函数有3个属性
resolve {Function} -是一个函数,它返回 request 被解析后得到的模块 id
keys {Function} -也是一个函数。返回的是匹配成功模块的名字组成的数组
id {String} - context module 的模块 id. 它可能在你使用 module.hot.accept
时会用到
注意:通过上面我们就知道了一个已知条件:如何去获取导入的组件 —> let 导入的组件 = require.context返回的函数(require.context返回的函数.keys ()中的每一项)
下图是require.context返回的函数
其中经常会用到的其实是keys 这个函数的返回数组,结构是[‘./A.vue’, ‘./B.vue’, ‘./C.vue’, ‘./ddddd.vue’]这样子的
我们都知道 Vue.component(参数1,参数2)是接收两个参数,第一个参数是注册的全局组件名字,第二个参数就是导入的组件。
1.解决第一个问题:组件名:利用keys 这个函数的返回数组,遍历该数组,然后利用正则把名字取出来
2.解决第二个问题:获取导入的组件(上面已知)
完整的在main.js全局组件导入的代码是这样子的:
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/\.vue$/
)
// 定义一个字符串转大写的方法
function upperFirst (*str*) {
const newStr = *str*.slice(0, 1).toUpperCase() + *str*.slice(1).toLowerCase()
return newStr
}
requireComponent.keys().forEach(*fileName* *=>* {
// 获取组件配置,其实就是获取你导入进来的每个组件,但是要用require.context返回的函数来执行,参数就是keys()数组中的每一项
const componentConfig = requireComponent(*fileName*)
// console.log(componentConfig)
// fileName的名字就是./A.vue 或者 ./B.vue ./B.vue ./ddddd.vue
// 写一个正则去匹配 .vue 或者 ./
// 然后就剩下一个文件名A,B B ddddd ,再字符串转大写,就可以注册大写字母开头的组件了。
const reg = /(\.\/)|\.vue/g
// 最终得到组件首字母大写的名字
const componentName = upperFirst(*fileName*.replace(reg, ''))
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
})
这些代码在main.js中有点多了,所以我们可以在component.js下面新建一个registerComponents.js文件,使用Vue.use的方式来注册,具体代码看demo就好了。
二、以引入vuex的module 来举例
这里的话,主要是借鉴了大佬花裤衩的vue-element-admin中vuex的引入方法。
具体代码就是:
const* modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
console.log(modulesFiles.keys())
*const* modules = modulesFiles.keys().reduce((*modules*, *modulePath*) *=>* {
// console.log(modules)
// console.log(modulePath)
// set './app.js' => 'app' 获取导入模块的名字
*const* moduleName = *modulePath*.replace(/^\.\/(.*)\.\w+$/, '$1')
// 拿到导入的模块
*const* value = modulesFiles(*modulePath*)
*modules*[moduleName] = value.default
// console.log(modules)
return *modules*
}, {})
*const* store = new Vuex.Store({
modules,
getters
})
其实require.context引入的思路都是一样的,只不过这一块需要对数组的reduce方法有所了解。他这里最后返回回去的modules就是一个对象
下图是返回回去的modules
可以自己去动手写一下,或者下载我的demo打开console.log()来查看一下,有助于理解