最近通过博客学习了import.meta.glob 函数从文件系统导入多个模块:
//匹配到的文件默认是懒加载的
const modules = import.meta.glob('./dir/*.js')
以上将会被转译为下面的样子:
// vite 生成的代码
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js')
}
当用其来进行路由引入的时候,由于需要在文件中进行判断是否注册为路由组件,所以在通过.then获得相应模块
//组件中
export default defineComponent({
name: 'home',
isRouter: true,//注册为路由
setup() {
}
})
//方法中
const modules = import.meta.glob('../views/**/*.vue')
for (const path in modules) {
modules[path]().then((mod) => {
const file = mod.default;
if (!file.isRouter) return //判断
router.addRoute({
path: `/${file.name}`,
name: `${file.name}`,
component: file //then方法访问到的模块
})
})
}
当通过遍历 modules 对象的 key并且.then后访问到了模块,后再用获取到的模块直接注册路由,这样会不会丧失路由的懒加载效果?
我一直在纠结如果不使用.then的话直接component:modules[key],就可以保留原始的路由懒加载格式,即component:()=>import('路径'),但使用.then后就直接变为了component:组件模块`(>﹏<)′
如果不好 可以采用这种
const modules = import.meta.glob("../views/**/**.vue")
let routerList: any = []
Object.keys(modules).forEach(key => {
const nameMatch = key.match(/^\.\.\/views\/(.+)\.vue/)
if (!nameMatch) return
const indexMatch = nameMatch[1].match(/(.*)\/Index$/i)
let name = indexMatch ? indexMatch[1] : nameMatch[1];
// 首字母转小写 letterToLowerCase 首字母转大写 letterToUpperCase
routerList.push({
path: `/${(name[0].toUpperCase() + name.slice(1))}`,
name: `${(name[0].toUpperCase() + name.slice(1))}`,
component: modules[key]
});
})
console.log(routerList, '===')
去vite的官方文档找线索, 发现vite升级到2.0的版本后, 多出一个方法, import.meta.glob, 可以动态引入路由, 一开始想着, 直接把后端传过来的用户页面权限路径放进这个方法里, 结果编译的时候报错, 参数不允许使用变量
没辙, 只能去翻一下vite的源码, 发现用的是typescript, 尝试改一下源码
把原来的注释掉, 把参数定义成any类型, 重新编译, 还是报错, 不晓得为什么, 改了没有效果, 没办法, 只能再去往下看源码, 发现他不止能接受一个页面地址, 还可以使用通配符, 知道这个, 我们就可以把项目中views下的文件都放进去, 然后再去判断用户拥有这个文件夹下面的哪些页面权限,
function addRouter(list) {
const modules = import.meta.glob("./views/**.vue");
for (const path in modules) {
modules[path]().then((mod) => {
const file = mod.default;
if (list.map((a) => a.name).includes(file.name)) {
router.addRoute({
path: "/" + file.name,
name: file.name,
component: file,
});
}
});
}
}
拿到的modules是一个对象, 进行遍历, 然后等待回调拿到页面信息, 其中list是当前用户所拥有的页面信息, 进行比对, 如果为true就addRoute添加路由. 把代码写完之后我们再打包, 重新上传到服务器, 再访问项目站点, 我们就可以发现, 路由已经没问题了, 切换页面也是正常显示的.
但是还有一个缺点, 因为这个方法是个异步的方法, 路由还没及时添加进去, 因此在刷新页面的时候, 页面还是空白, 需要再点击一下菜单栏才能正常显示, 这个问题我暂时还没有解决方案, 不得不说, 使用新技术风险太大了, 很多意想不到的坑在等着你跳, 网上的资料又不全, 只能硬着头皮去尝试解决.