require.context
require.context是什么
require.context是webpack中的一个api,通过执行这个api会返回一个特定的上下文(一个对象里面保存了很多有用的状态),主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹中引入很多模块的情况,可以使用这个api,它会遍历文件夹中指定文件然后自动导入上下文,使得不需要每次都要显式的调用import导入模块.import是导入文件,require.context是导入模块中匹配的所有文件.
require.context介绍
require.context接受三个参数
- directory {String} -读取文件的路径
- useSubdirectories {Boolean} -是否遍历文件的子目录
- regExp {RegExp} -匹配文件的正则 例子:
require.context('./test', false, /.test.js$/);
上面代码的意思是遍历test文件夹下的所有匹配以.test.js结尾的文件,不遍历子项目.
调用require.context('./test', false, /.test.js$/)会得到test文件夹下文件的执行环境也就是上下文,里面包含了文件的有用信息.值得注意的是require.context函数执行后返回的上下文包含三个属性:
- resolve {Function} -接受一个参数request,request为test文件夹下面匹配文件的文件名,返回这个匹配文件相对于整个工程的相对路径
- keys {Function} -返回匹配成功模块的名字组成的数组
- id {String} -执行环境的id,返回的是一个字符串,主要用在module.hot.accept,应该是热加载 这三个都是作为函数的属性(注意是作为函数的属性,函数也是对象,有对应的属性).
注意require.context函数执行后返回的上下文函数也接受一个req参数,这个参数和resolve方法的参数是一样的,即匹配文件名的文件名,执行之后就表示导入这个模块,等同于import,并且会返回一个模块数据.
上代码,如图:
import Vue from 'vue'
import moduleImport from '../components/CommitResult/commitFail.vue'
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
const requireComponent = require.context(
'../components/CommitResult', false, /\.vue$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = capitalizeFirstLetter(
fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')
)
Vue.component(componentName, componentConfig.default)
})
console.dir(requireComponent)
console.log('requireComponent', requireComponent)
console.log('keys', requireComponent.keys())
console.log('id', requireComponent.id)
console.log('resolve', requireComponent.resolve(requireComponent.keys()[0]))
console.log('module', requireComponent(requireComponent.keys()[0]))
console.log('moduleImport', moduleImport)
总结:console.dir可以打印这个对象的属性和值,只有一个参数,console.log是直接打印这个对象,可以传两个参数,module和moduleImport都表示导入这个模块.简单来说require.context函数接受三个参数,执行之后返回的函数体包含三个属性,这个函数体也可以接受一个参数,这个参数是匹配文件的文件名,执行就表示引入这个模块,等同于import,返回的是模块数据.
参考文章:www.cnblogs.com/cangqinglan…
使用场景
引入svg
import Vue from 'vue'
import SvgIcon from '@/components/svgIcon'
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().forEach(requireContext)
requireAll(req)
全局注册组件
import Vue from 'vue'
import moduleImport from '../components/CommitResult/commitFail.vue'
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
const requireComponent = require.context(
'../components/CommitResult', false, /\.vue$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = capitalizeFirstLetter(
fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')
)
Vue.component(componentName, componentConfig.default)
})
注册路由
样式选择器
如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符,有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/,但是有些开发者反应,在vue-cli3编译时,deep的方式会报错或者警告。此时我们可以使用第三种方式::v-deep。通过 v-html 创建的 DOM 内容不受 scoped 样式影响,但是你仍然可以通过深度作用选择器来为他们设置样式。