vue3 vite 动态加载路由遇到的问题
记录一下动态加载路由遇到的问题
正常使用import引入静态路由是没问题的
component: () => import('@/components/ExampleComponent.vue')
动态引入的时候写成import就不行了
由于后端给的路由格式比较反人类…我这边先递归把获取到的数据格式做了一个整合.
const processedData = res.data.map((item) => {
// 递归函数来处理子路由
const processChildren = (children) =>
(children || []).map((childItem) => ({
path: childItem.path,
name: childItem.name,
component: childItem.permsLevel == 1 ? 'Layout' : childItem.path, // 如果菜单是一级
meta: {
id: childItem.id,
icon: childItem.icon || undefined,
title: childItem.title,
},
// 递归处理更深层次的子路由
...(childItem.menuTwoList || childItem.menuThreeList
? {
children: processChildren(childItem.menuTwoList || childItem.menuThreeList),
}
: {}),
}))
// 创建一个新对象以避免直接修改原始数据
const route = {
path: item.path,
name: item.name,
component: item.permsLevel == 1 ? 'Layout' : item.path,
meta: {
id: item.id,
icon: item.icon || undefined,
title: item.title,
},
// 递归处理子路由
...(item.menuTwoList || item.menuThreeList
? {
children: processChildren(item.menuTwoList || item.menuThreeList),
}
: {}),
}
// 这里要注意的就是如果子路由没有children一定要删除,不然点击显示不出来Layout
if (route.children.length == 0) {
delete route.children
}
return route
})
// 我这边是因为后端给的children可能叫menuTwoList 或者menuThreeList才进行这样的处理
// 如果大家只是都叫children就不需要这样了
现在我们拿到的数据就是正常的路由格式了,但是还差一步动态引入路由
在permission.ts里面找到router.beforeEach,就是咱们的路由守卫了
if (to.path === '/login') {
// 如果已登录,请重定向到主页
next({ path: '/' })
} else {
try {
const PermissionStore = usePermissionStore()
// 路由添加进去了没有及时更新 需要重新进去一次拦截
if (!PermissionStore.routes.length) {
// 获取权限列表进行接口访问 因为这里页面要切换权限
const accessRoutes = await PermissionStore.generateRoutes(UserStore.roles)
hasRoles = false
// 在这里进行动态路由的添加
await processRoutes(accessRoutes)
next({ ...to, replace: true }) // // 这里相当于push到一个页面 不在进入路由拦截
} else {
next() // // 如果不传参数就会重新执行路由拦截,重新进到这里
}
} catch (error) {
next(`/login?redirect=${to.path}`)
}
}
processRoutes和resolveComponent的方法我就贴在这边大家参考一下
const modules = import.meta.glob('/src/views/**/*.vue')
const layout = import.meta.glob('/src/layout/**/*.vue')
// 记录路由
const resolveComponent = (path: string, type: any) => {
// 拿到views下面的所有文件之后,动态拼接`key`去获取value
const importPage = type ? modules[`/src/views${path}.vue`] : layout[`/src/${path}.vue`]
// console.log(importPage)
if (!importPage) {
throw new Error(`Unknown page ${path}. Is it located under Pages with a .vue extension?`)
}
return importPage
}
const processRoutes = async (routes) => {
routes.forEach((item) => {
// 检查当前路由项是否需要替换组件
if (item.component === 'Layout') {
item.component = resolveComponent('layout/index', null)
} else {
item.component = resolveComponent(item.path, 1)
}
// 添加当前路由到路由器
// 如果当前路由项有子路由,则递归处理
if (item.children && Array.isArray(item.children)) {
processRoutes(item.children)
}
router.addRoute(item)
})
}
完结
觉得写的比较全面的请给一个小星星.谢谢~