为什么使用动态路由?
因为后台会存在角色,角色中会有不同的菜单数据,这里面就会出现路由不能写死的问题?如何解决,上动态路由。
设计思路
- 登录的时候对异步请求数据保存到
localstorage
中
- 在
router.beforeEach
路由守卫中添加 localstorage
菜单数据加载
- 根据加载的菜单数据,递归加载组件,因为本地只保存
component
路径
- 最后使用
router.addRoutes
将组装好的数据填充进来就完成了
坑点
为什么路由不报错,进入该路由界面无显示任何数据?
这是因为思想出问题了,一开始在登录中将 component
直接 import
进来了,然后再保存到 localstorage
。所以理所当然认为本地保存了组件信息,这个和周总(同事)讨论过。他也不知道怎么回事,但是我突然就说没有加载组件进来,果然陷入思维困局需要第二者。
解决方案:
component
字段保存组件路径,在需要加载的时候再 import
进来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function BuildRoutes(routes) { let element = { name: routes.name, path: routes.path, component: () => import(`@/${routes.component}.vue`), };
if (routes.component == "") { delete element.component; }
if (!isNull(routes.children) || !isUndefined(routes.children)) { element.children = []; routes.children.forEach((item) => { element.children.push(BuildRoutes(item)); });
return element; } return element; }
|
如何保证无路由时后台获取?
正如标题所讲,我首先的思路就是在 router.beforeEach
中判断无路由就直接后台请求获取。这样子做就会有一个问题,那就是如何判断后台数据获取到了的问题。因为在守卫中是同步的,而我在这里使用的是异步库 axios
。所以这里就会导致短期会有多个请求
解决方案:
将路由信息在登录中保存,这样子就不会出现多次请求问题,因为登录只会进行一次,所以请求后台数据并保存到本地也只会是一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function dynamicBuild(source) { let element = { name: source.label, path: source.full_url, component: source.component, };
if (source.children != null) { element.children = []; source.children.forEach((item) => { element.children.push(dynamicBuild(item)); });
return element; }
return element; }
|
1 2 3 4 5 6 7 8 9
| generateRoutes: (state, routes) => { state.addRouters = routes; let routers = BuildRoutes(routes); if (isObject(routers)) { routers = [routers]; } router.addRoutes(routers); };
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| function dynamicRouter() { menuList().then((res) => { let backendRouter; backendRouter = dynamicBuild(res.data.data[0]); storage.setItem({ name: "backend_router", value: backendRouter, expires: new Date().getTime() + 60 * 60 * 1000, }); store.dispatch("GenerateRoutes", backendRouter); }); }
|
如何保证动态路由信息不会重复添加?
首先在路由守卫当中,我们要保证添加过路由后就不再添加进来。所以我们就要在全局中保存所需要的信息,这里买了 vuex
就是非常好的方法。首先我们应该在 state
中添加一个 addRouters
变量,默认是 null
然后就可以根据这个值来判断是否需要添加了。