动态路由主要采用的是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)
}
})
}