动态路由主要采用的是router.addRoutes添加动态路由

思路分析

  1. 前后端数据需要进行对比,动态路由需要给父级路由设置默认重定向
    1. 在utils包中定义两个方法
    2. 主要采用递归的方式
  2. 采用路由导航守卫,对路由跳转进行监控,判断其是否登录,是否有权限,并添加动态路由等
  3. 在store中处理动态路由

    代码实现

    导航守卫

    1. import router from './index'
    2. import store from '../store/index'
    3. router.beforeEach((to, from, next) => {
    4. if (!store.state.userToken) {
    5. // 未登录
    6. if (!to.name || to.matched.some(record => record.meta.requireAuth)) {
    7. // 页面需要登录
    8. // matched存放了路径的所有路由,包括父路由和子路由
    9. // 父路由或子路由中的任意一个路由‘requireAuth’为真,都要跳转到登录页
    10. // 也就是在设置时,只需要将父路由的requireAuth=true,就可以控制所有子路由了
    11. next({ path: '/login' })
    12. } else {
    13. next()
    14. }
    15. } else {
    16. // 已登录 判断权限
    17. if (to.path === '/login') {
    18. // 已登录不能再去登录页面
    19. next('/')
    20. } else if (store.state.permissions.permissionRoutes.length === 0) {
    21. // 动态路由还未加载
    22. // 加载动态路由
    23. store.dispatch('setRoutes', store.state.userToken).then(routes => {
    24. // 添加动态路由
    25. router.addRoutes(routes)
    26. // 使用以下方法,可以中断当前导航,再次进入导航守卫,这样可以确保addRoutes已完成
    27. next({ ...to, replace: true })
    28. })
    29. } else {
    30. if (to.name) {
    31. next()
    32. } else {
    33. // 路由不存在就去404页面
    34. next('/404')
    35. }
    36. }
    37. }
    38. })

    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 } } }

  1. <a name="z56oD"></a>
  2. #### utils对比动态路由和设置默认路由方法
  3. ```javascript
  4. // 对比前后端路由,获取有权限的动态路由
  5. export function diffRoutes(allroutes = [], userRoutes = []) {
  6. const realRoutes = []
  7. allroutes.forEach(r => {
  8. userRoutes.forEach(item => {
  9. if (r.meta.name === item.name) {
  10. if (item.children && item.children.length > 0) {
  11. // 递归处理子路由
  12. r.children = diffRoutes(r.children, item.children)
  13. } else {
  14. r.children = []
  15. }
  16. realRoutes.push(r)
  17. }
  18. })
  19. })
  20. return realRoutes
  21. }
  22. // 为路由设置重定向,默认是当前路由的第一个子路由
  23. export function defaultRoute(allroutes) {
  24. allroutes.forEach(r => {
  25. if (r.children && r.children.length > 0) {
  26. r.redirect = r.path + '/' + r.children[0].path
  27. // 递归处理子路由
  28. defaultRoute(r.children)
  29. }
  30. })
  31. }