前端读取文件夹中文件的方式以及使用技巧
写在前面
场景:现在的前端项目都是基于模块化来开发的。
问题:如何快捷、优雅的引入相同类型的多个文件呢?
例如:
- 在
vuex
的使用场景中按业务或者模块组件来创建多个对应的module.js
文件; - 在
vue-router
的使用场景中按页面 模块划分,创建多个路由文件; - 在自定义组件/指令的时候,创建了多个组件/指令文件;
如何快速的引入或者注册这些文件呢?像下面这样吗?
【以 vue-router
为例】
// 以 vue-router 为例
import HomeRouter from './modules/home.js'
import LoginRouter from './modules/login.js'
// ... 重复上面的
const asyncRouterMap = []
asyncRouterMap.push(HomeRouter)
asyncRouterMap.push(LoginRouter)
// ... 重复上面的
【以 vuex
为例】
import baseModule from './modules/base.js'
import settingModule from './modules/setting.js'
import userModule from './modules/user.js'
// ... 重复上面的
const store = createStore({
modules: {
base: baseModule,
setting: settingModule,
user: userModule
}
})
这显然是不优雅的!
正文
认识 require.context
require.context
是 webpack
中,用来创建自己的 context module
上下文(模块)。
webpack
会在构建的时候解析代码中的 require.context()
![](/qrcode.jpg)
语法: require.context(directory, useSubdirectories, regExp)
require.context
函数接收三个参数:
- 1、
directory
; 要搜索的文件夹目录 - 2、
useSubdirectories
; 表示是否检索子文件夹 - 3、
regExp
; 匹配文件的正则表达式
如果想引入一个文件夹下面的所有文件,或者引入能匹配一个正则表达式的所有文件,这个功能就会很有帮助。
【语法示例1】
const modulesFiles = require.context('./modules', true, /\.js$/)
【语法示例2】
const modulesFiles = require.context('./modules', false, /\.vue$/)
一个 context module
会导出一个(require
)函数,此函数可以接收一个参数: request
。 此导出函数有三个属性:resolve
, keys
, id
。
resolve
是一个函数,它返回request
被解析后得到的模块id
。keys
也是一个函数,它返回一个数组,由所有可能被此context module
处理的请求组成。id
是context module
的模块id
。 它可能在你使用module.hot.accept
时会用到。
【使用示例1】
const cache = {
}
const modulesFiles = require.context('./modules', true, /\.js$/)
modulesFiles.keys().forEach((key) => {
cache[key] = r(key)
})
【使用示例2】
const cache = {
};
function importAll(r) {
r.keys().forEach((key) => (cache[key] = r(key)));
}
importAll(require.context('../components/', true, /\.js$/));
// 在构建时(build-time),所有被 require 的模块都会被填充到 cache 对象中。
这一切都要得益于 Webpack 出色的表现和性能。
项目中的使用示例
【使用示例一、在 vuex
中的使用】
不管你 modules
中有多少个 js
文件
/**
* 自动读取modules文件夹中的vuex模块
* 不用手动引入和注入
*/
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {
})
/**
* 这里getters是单独拿出来的,全局统一用一个,用做取值的便捷手段。【也是官方推荐的】
* 你也可以直接使用 this.$store.state.[moduleName].[paramName] 来取值
* (PS:至于state,mutations,actions就由每个modules文件夹里面的文件,自己实现)
*/
const getters = {
// 用户信息
allInfo: state => state.user.userInfo,
// 用户名
name: state => state.user.userInfo.name,
// 头像
avatar: state => state.user.userInfo.avatar,
// 语言
language: state => state.language.language,
// add_routes 是动态遍历出来,添加上去的路由
addRoutes: state => state.permission.addRoutes,
// 用户的原始permissions数据
permissions: state => state.user.permissions,
// 用户的路由菜单权限(完整的)
routers: state => state.permission.routes
}
export default new Vuex.Store({
modules,
getters
})
【使用示例二、在 vuex
中的使用(与使用示例一相似)】
import getters from './getters'
// https://webpack.js.org/guides/dependency-management/#requirecontext
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
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {
})
export default createStore({
modules,
getters
})
【使用示例三、批量注册 mixins
】
// src/mixins/index.js
const modulesFiles = require.context('./modules', true, /\.js$/)
const mixinsModules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {
})
export default mixinsModules
// 在组件中使用时
import mixinsModules from '@/mixins/index.js
...
mixins: [mixinsModules.userMixin, mixinsModules.appMixin]
【使用示例四、批量注册 vue-router
】
const asyncRoutes = []
/**
* 如果系统页面模块比较多,也可以分模块写
*/
/**
* 自动扫描 modules 里面的路由模块,路由模块请根据业务自行拆分
* modules 里面只能存放动态路由(需要根据权限来选择的路由)
* 插入到 asyncRoutes 中
* 基础路由全部写到constantRoutes中
*/
const files = require.context('./modules', false, /\.js$/)
files.keys().forEach(key => {
const file = files(key).default
// 根据导出的内容判断是否数组,如果数组需使用扩展运算符
if (Array.isArray(file)) {
asyncRoutes.push(...file)
} else {
asyncRoutes.push(file)
}
})
—————————— 【正文完】——————————
前端学习交流群,想进来面基的,可以加群: 832485817,685486827;
写在最后: 约定优于配置 —— 软件开发的简约原则
——————————【完】——————————
我的:
个人网站: https://neveryu.github.io/neveryu/
Github: https://github.com/Neveryu
新浪微博: https://weibo.com/Neveryu
微信: miracle421354532
更多学习资源请关注我的新浪微博…好吗