Vue3中简单实现动态添加路由
作者:bald3r
本文主要介绍了Vue3中简单实现动态添加路由,,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
前言
通过后端接口的返回值,动态添加路由,是作为权限控制的一种常见方式,本文将简单讲解如何在Vue3中动态添加路由。
示例数据
[ { "id": 1, "pid": 0, "url": "/dashboard", "title": "控制面板板", "component": "/src/views/dashboard/DashboardView.vue", "icon": "SlidersOutlined", "is_show": 0, "level": 1, "sort": 1, "order": "1", "type": "menu", "status": 0, "children": null }, { "id": 2, "pid": 0, "url": "/system", "title": "系统设置", "component": null, "icon": "ToolOutlined", "is_show": 0, "level": 1, "sort": 7, "order": "2", "type": "menu_dir", "tips": null, "status": 0, "children": [ { "id": 7, "pid": 2, "url": "/system/menu", "title": "菜单管理", "component": "/src/views/system/MenuView.vue", "icon": "BarsOutlined", "is_show": 0, "level": 2, "sort": 3, "order": "2,7", "type": "menu", "tips": null, "status": 0, "children": [ { "id": 8, "pid": 7, "url": "/system/menu/add", "title": "新增菜单", "component": null, "icon": null, "is_show": 1, "level": 3, "sort": 1, "order": "2,7,8", "type": "button", "tips": null, "status": 0, "children": null } ] } ] }, ]
思路分析
动态添加路由的实质,就是先将后端返回的json数据转化成一个个RouteRecordRaw
形式的对象,然后调用Vue Router的addRoute
方法,添加进路由列表中。由于每个路由地址都会对应一个Vue组件,因此还需要将Vue组件都通过import.meta.glob
读取到内存中。
具体实现函数
const viewsComponent: Record<string, any> = import.meta.glob("/src/views/**/*.vue", { eager: true }) const addRouteAll = (menu: RoleMenu[]) => { //RoleMenu就是接口返回的数据的类型 menu.forEach(item => { if (item.type === "menu" && viewsComponent[item.component]) { addRouteItem(item) } if (item.children && item.children.length > 0) { addRouteAll(item.children) } }) } const addRouteItem = (route: RoleMenu) => { const path = route.url const component = viewsComponent[route.component] const routeBaseInfo: RouteRecordRaw = { path, name: path.substring(1), component: component.default, meta: { title: route.title, icon: route.icon, keepalive: route.children && route.children.length > 0 ? 0 : path.substring(1), menu_type: "tab", type: route.type, url: route.url, addTab: true } } router.addRoute(routeBaseInfo) }
存在问题
路由何时处理?
笔者一开始认为,登录成功后立刻调用获取菜单的接口,然后处理路由,因此路由的处理应该在登录页面中的登录请求成功后进行处理,但是此时存在一个问题,用户登录成功进入后台页面,然后用户刷新页面,就会提示导航失败,控制台也会报错,因此笔者认为应该在登录成功进入后台页面之后开始处理。
笔者后台的主体页面框架为MainLayout
,因此笔者在此进行路由处理。
const getMenu = () => { apiAuthMenuList().then(res => { menuList.value = handleMenu(res.content) //菜单处理 addRouteAll(res.content) }) } onMounted(() => { getMenu() })
导航失败
⚠️ [Vue Router warn] : No match found for location with path "/dashboard"
这是因为路由跳转的时机要早于组件挂载,因此在组件挂载并处理路由前,路由就已经跳转并报错了。
笔者解决这个问题的思路有两个:
- 首先定义全局变量
routeReady
,初始值为false
,当路由处理完成后变为true
- 在路由守卫
beforeEach
中判断,如果routeReady
为false
则处理路由,处理完成后跳转。 - 创建一个Loading页面,如果路由没有匹配的地址则跳转至Loading页面,并在该页面进行判断:
- 如果
routeReady
为true
,说明去往的地址并不在该用户的权限菜单中,转向404页面 - 如果
routeReady
为false
,则说明路由未加载完成,那么就在当前页面等待,等routeReady
为true
时,再执行上面的判断
- 如果
笔者这里用了方法2。
//截获所有未匹配的路由,进入Loading页面 { path: "/:pathMatch(.*)*", component: () => import("../views/LoadingView.vue") }
//LoadingView.vue watchEffect(() => { if (globalStore.routeReady) { const routeList = router.getRoutes() if (routeList.find(i => i.path === router.currentRoute.value.fullPath)) { router.push(router.currentRoute.value.fullPath) } else { router.push("/notFound") } } })
通过这种方式,可以在用户刷新页面后有一个顺滑的体验。
进入第一个路由
目前还存在一个问题,用户在登录跳转后,会进入后台页面,但是此时不会进入到任一菜单中:
而我们希望登录跳转后能自动进入到第一个菜单,即:
因此我们需要一个方法来找到第一个可用的路由:
const getFirstRoute = (routes: RouteRecordRaw[]): false | RouteRecordRaw => { const routerPaths: string[] = [] const routers = router.getRoutes() routers.forEach(item => { if (item.path) routerPaths.push(item.path) }) let find: boolean | RouteRecordRaw = false for (const key in routes) { if (routes[key].meta?.type != "menu_dir" && routerPaths.indexOf(routes[key].path) !== -1) { return routes[key] } else if (routes[key].children && routes[key].children?.length) { find = getFirstRoute(routes[key].children!) if (find) return find } } return find }
然后调用这个方法即可:
const init = () => { const firstRoute = getFirstRoute(menuList.value!) if (firstRoute) { router.push(firstRoute.path) } } onMounted(() => { init() })
后记
到此这篇关于Vue3中简单实现动态添加路由的文章就介绍到这了,更多相关Vue3动态添加路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!