赞
踩
思路:
总的来说就是从后端拿到路由数据,动态添加到路由表中。
问题:
如果有登录得先配置静态路由
细节:
1. 在路由中配置静态路由: //定义静态路由 const staticRoutes = [ { path: '/login', name: 'Login', component: () => import(/* webpackChunkName: "Login" */ '../views/Login'), }, ]; 2. 在路由中设置路由守卫 //定义全局守卫 router.beforeEach(async (to, from, next) => { //获取登录状态 const token = localStorage.getItem('token'); if (!token && to.name !== 'Login') { return next('/login'); } else if (!token && to.name === 'Login') { if (!token) next(); } else { if (!store.state.hasGetRoute) { // 如果没有获取路由信息,先从vuex获取路由信息而后跳转 store.dispatch('getRouteList').then(() => { router.addRoutes(store.state.routeList); // 如果直接使用 next() 刷新后会一直白屏 next({ ...to, replace: true }); }); } else { // 如果已经获取路由信息,直接跳转 next(); } } }); 3.vuex的中一些配置 const store = new Vuex.Store({ state: { routeList: [], hasGetRoute: false, }, mutations: { setRouteList(state, data) { // 用路由解析函数解析 List 为真正的路由列表 state.routeList = filterAsyncRouter(data); // 修改路由获取状态 state.hasGetRoute = true; }, }, actions: { getRouteList({ commit }) { return new Promise(resolve => { //axios获取路由结构 MetroApi({ url: '/user/get-user', }).then(res1 => { MetroApi({ url: '/role/menu-list', params: { roleId: res1.data.roleId, }, }).then(res => { let data = res.data; //循环遍历出route结构,并添加动态路由 let navList = data.map(item => { return { name: item.menuName, path: item.frontPath, }; }); localStorage.setItem('navList', JSON.stringify(navList)); let routes = [ { path: '/', name: 'Index', component: () => import('@/components/Layout'), redirect: 'Workbench', children: [...data], }, ]; // 注意这里取出的是 JSON 格式的路由列表 commit('setRouteList', routes); resolve(); }); }); }); }, }, }); 4.vuex中一些额外的方法 const loadView = viewPath => { // 用字符串模板实现动态 import 从而实现路由懒加载 return () => import(`@/views${viewPath}`); }; const filterAsyncRouter = routeList => { return routeList.filter(route => { if (route.frontPathComponent) { // 利用懒加载函数将实际页面赋值给它 route.component = loadView(route.frontPathComponent); route.name = route.menuName; route.path = route.frontPathComponent || '/'; if (route.menuType === 'M' && route.children.length > 0) { route.redirect = route.children[0].frontPathComponent; } } // 判断是否存在子路由,并递归调用自己,如果不是路由就去掉(C、M这个是后台传来的层级) if (route.menuType === 'C') { route.children = []; } if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children); } return true; }); };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。