动态路由主要采用的是router.addRoutes添加动态路由
思路分析
- 前后端数据需要进行对比,动态路由需要给父级路由设置默认重定向
- 在utils包中定义两个方法
- 主要采用递归的方式
- 采用路由导航守卫,对路由跳转进行监控,判断其是否登录,是否有权限,并添加动态路由等
- 在store中处理动态路由
代码实现
导航守卫
import router from './index'import store from '../store/index'router.beforeEach((to, from, next) => {if (!store.state.userToken) {// 未登录if (!to.name || to.matched.some(record => record.meta.requireAuth)) {// 页面需要登录// matched存放了路径的所有路由,包括父路由和子路由// 父路由或子路由中的任意一个路由‘requireAuth’为真,都要跳转到登录页// 也就是在设置时,只需要将父路由的requireAuth=true,就可以控制所有子路由了next({ path: '/login' })} else {next()}} else {// 已登录 判断权限if (to.path === '/login') {// 已登录不能再去登录页面next('/')} else if (store.state.permissions.permissionRoutes.length === 0) {// 动态路由还未加载// 加载动态路由store.dispatch('setRoutes', store.state.userToken).then(routes => {// 添加动态路由router.addRoutes(routes)// 使用以下方法,可以中断当前导航,再次进入导航守卫,这样可以确保addRoutes已完成next({ ...to, replace: true })})} else {if (to.name) {next()} else {// 路由不存在就去404页面next('/404')}}}})
store中处理动态路由
```javascript import { getPermissions } from ‘../../api/permission.js’ import { dynamicDefaultRoutes } from ‘@/router/index.js’ import { diffRoutes, defaultRoute } from ‘@/utils/deal-route.js’ import dynamicRoutes from ‘../../router/dynamic-routes’
export default { state: { permissionRoutes: [] // 存储动态路由 }, mutations: { SET_ROUTES(state, routes) { state.permissionRoutes = routes }, CLEAR_ROUTES(state) { state.permissionRoutes = null } }, actions: { async setRoutes({ commit }, token) { // 获取后台路由权限 let res = await getPermissions({ user: token }) // 对比后台权限与前端所有动态路由,得到有权限的路由 let routes = diffRoutes(dynamicRoutes, res.data) // 处理动态路由的重定向 defaultRoute(routes) // 获取默认路由中的layout根路由,并将动态路由设置为其子路由 let container = dynamicDefaultRoutes.find(r => r.path === ‘’) container.children.push(…routes) commit(‘SET_ROUTES’, dynamicDefaultRoutes) // 返回动态路由,在路由导航中添加动态路由 return dynamicDefaultRoutes } } }
<a name="z56oD"></a>#### utils对比动态路由和设置默认路由方法```javascript// 对比前后端路由,获取有权限的动态路由export function diffRoutes(allroutes = [], userRoutes = []) {const realRoutes = []allroutes.forEach(r => {userRoutes.forEach(item => {if (r.meta.name === item.name) {if (item.children && item.children.length > 0) {// 递归处理子路由r.children = diffRoutes(r.children, item.children)} else {r.children = []}realRoutes.push(r)}})})return realRoutes}// 为路由设置重定向,默认是当前路由的第一个子路由export function defaultRoute(allroutes) {allroutes.forEach(r => {if (r.children && r.children.length > 0) {r.redirect = r.path + '/' + r.children[0].path// 递归处理子路由defaultRoute(r.children)}})}
