记录一下动态加载路由遇到的问题
正常使用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一定要删除,不然点击显示不出来Layoutif (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`去获取valueconst 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)})
}
完结
觉得写的比较全面的请给一个小星星.谢谢~