前端思路:
上图中 获取路由信息 ,可以是后端控制的,可以是前端根据用户信息从路由表中筛选的。
此处只讲解后端存储路由信息的情况
请求后台,获取返回结果,结果有两种可能,一种是组合好的树状结构,一种是路由平铺
树状结构:
不需要重组路由结构,但是需要替换组件信息
- import components from '@/router/components'
-
- /* 遍历后台传来的路由字符串,转换为组件对象
- * @params asyncRouterMap MyRoute[] 异步路由数组
- * @params type boolean 是否需要重写子路由路径
- */
- function filterAsyncRouter(asyncRouterMap: MyRoute[], type = false) {
- return asyncRouterMap.filter(route => {
-
- if (type && route.children) {
- route.children = rewriteChildrenPath(route.children, route)
- }
- if (route.component) {
- // 如果路径组件在路由表中查询不到,默认渲染NotFound组件,其他情况可自定义处理
- if (!Object.keys(components).includes(route.component as string)) {
- route.component = components.NotFound
- } else {
- route.component = components[route.component as keyof typeof components]
- }
- }
- if (route.children != null && route.children && route.children.length) {
- route.children = filterAsyncRouter(route.children, type)
- } else {
- delete route[`children`]
- delete route[`redirect`]
- }
- return true
- })
- }
-
- /* 重写路由中子路由路径
- * @params childernMap MyRoute[] 子路由数组信息
- * @params lastRouter MyRoute 父路由信息
- */
- function rewriteChildrenPath(childrenMap: MyRoute[], lastRouter: MyRoute) {
- let children: MyRoute[] = []
- childrenMap.forEach((el) => {
- el.path = `${lastRouter.path }/${ el.path}`
- children = children.concat(el)
- })
- return children
- }
路由平铺
此时除了替换组件信息,还需要构建树状路由结构
let routes = res.map(organizeRoute) //organizeMenu 工具函数 重组路由结构
routes = recursiveData(routes, ``)
- import Components from '@/routers/component'
-
- // 菜单组织为route形式
- const organizeRoute= (route) => {
- // 防止顶级路由未加斜杠报错
- const path = route.path.indexOf(`/`) !== 0 ? `/${route.path}` : route.path
- const _route= {
- //...符合route的属性和其他自定义属性
- component: route.component && Components[route.component] || Components.NotFound,
- meta: {
- title: route.title,
- hidden: route.hidden,
- icon: route.icon,
- //...其他自定义属性
- },
- query: {},
- params: {},
- }
- // 重定向
- route.redirect && Object.assign(_route, { redirect: { name: route.redirect } })
- return _route
- }
-
-
- //重组树状路由结构
- const organizeRouteTree= (routes, pid = `0`) => {
- const _routes= routes.filter(item => item.pid === pid) //找出所有父级路由
-
- if (!_routes|| _routes.length === 0) return []
-
- _routes.sort((prev, next) => {
- return prev.sort - next.sort
- })
- _routes.map(item => {
- const children = organizeRouteTree(routes, item.id)
- children && children.length > 0 && (item.children = children)
- })
- return _routes
- }
路由守卫中动态添加
- //获取用户信息
- userStore.getUserInfo()
- .then(() => {
- //isRelogin.show = false
- perssionStore.getRoutes()
- .then(accessRoutes => { //accessRoutes上一步中处理好的树状路由信息
- accessRoutes.forEach(route => {
- if (!isHttp(route.path)) {
- router.addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
- }
- })
- next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
- })
- })
- .catch(err => {
- userStore.logOut()
- .then(() => {
- notification.error({
- message: err.code,
- description: err.message || err.msg,
- })
- next({ path: `/` })
- })
- })
-
-
- /**
- * 判断url是否是http或https
- * @param {string} path
- * @returns {Boolean}
- */
- export function isHttp(url:string) {
- return url.indexOf(`http://`) !== -1 || url.indexOf(`https://`) !== -1
- }
非路由守卫中添加
const createRouter = (routes = []) => {
const _routes = [...baseRoutes, ...routes]
return new Router({
mode: `hash`,
routes: _routes,
scrollBehavior: () => ({ y: 0 }),
})
}const router = createRouter()
export function resetRouter (routes = []) {
const newRouter = createRouter(routes)
router.matcher = newRouter.matcher // the relevant part
}