问答

Vue Router 获取 addRoutes 动态添加的路由

作者:admin 2021-05-09 我要评论

有没有方法获取通过 addRoutes 添加的路由表 ### 既然是addRoutes添加的,在添加的时候保存一下就好了 ### 所谓的路由,其实就是一个对象或者对象数组。既然是对...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

有没有方法获取通过 addRoutes 添加的路由表

###

既然是addRoutes添加的,在添加的时候保存一下就好了

###

所谓的路由,其实就是一个对象或者对象数组。既然是对象或者对象数组,这就好处理了啊。
在vue-cli2搭建的项目中,router文件夹下index.js就是路由文件。

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

/* @meta
 * icon: ''                      菜单图标(支持el-icon)
 * title: ''                     菜单标题
 * isPermit                      是否需要权限
 * keepAlive: false              是否需要缓存(需要name才能生效)
 * hidden: false                 是否显示在菜单
 * affix: false                  是否常驻在tagNav组件上(外链无效)
 **/

//基础路由
export const constantRoutes = [
  {
    path: '/',
    component: PageIndex,
    redirect: '/main',
    meta: {
      title: '系统首页',
      icon: 'el-icon-folder-opened',
      isPermit: true,
      keepAlive: true,
      hidden: false,
      affix: true,
    },
    children: [
      {
        path: '/main',
        name: 'Dashboard',
        component: () => import('@/views/index/dashboard'),
        meta: {
          title: '系统首页',
          icon: 'el-icon-document',
          isPermit: true,
          keepAlive: true,
          hidden: false,
          affix: true,
        },
      },
    ],
  },
  {
    path: '/login',
    component: () => import('@/views/index/login'),
    meta: {
      title: '登录页面',
    },
  },
  {
    path: '/page404',
    component: () => import('@/components/error/page404'),
    meta: {
      title: '404页面',
    },
  },
]

// 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

const createRouter = () =>
  new Router({
    mode: 'history',
    //mode: 'hash',
    routes: constantRoutes,
    scrollBehavior: () => ({ y: 0 }),
  })

const router = createRouter()

export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

通过设置基础路由constantRoutes,使用户具有最基础的访问功能,然后通过权限来获取菜单选项来动态加载路由。
在store文件夹module内新建routes.js文件,通过addRoutes动态加载路由

import { localRoutes, asyncRoutes } from '@/router'

export default {
  namespaced: true,
  state: {
    allRoutes: [], // 全部路由
    sideRoutes: [] // 侧边栏路由
  },
  mutations: {
    SET_ALL_ROUTES: (state, routes) => {
      state.allRoutes = [...routes]
    },
    SET_SIDE_ROUTES: (state, routes) => {
      state.sideRoutes = [...routes]
    }
  },
  actions: {
    generateRoutes ({ commit }) {
      return new Promise(resolve => {
        // 这里可以根据项目需求自行对asyncRoutes进行过滤得到finalAsyncRoutes
        const finalAsyncRoutes = [...asyncRoutes]
        let finalAsyncParentRoutes = { ...asyncParentRoutes }
        finalAsyncParentRoutes.children = [...finalAsyncRoutes, extraPanentRoutes]
        const sideRoutes = setRedirect([finalAsyncParentRoutes])
        const addRoutes = [...sideRoutes, extraGlobalRoutes] // 实际动态添加的路由
        const allRoutes = [...localRoutes, ...addRoutes] // 所有路由
        commit('SET_SIDE_ROUTES', sideRoutes)
        commit('SET_ALL_ROUTES', allRoutes)
        resolve(addRoutes)
      })
    }
  }
}

其中localRoutes,asyncRoutes分别就是一个菜单树形数组

export const localRoutes = [
  {
    path: '',
    redirect: '/login'
  },
  {
    path: '/login',
    component: () => import('@/pages/login/login')
  },
  {
    path: '/page401',
    component: () => import('@/pages/other/page401')
  },
  {
    path: '/page404',
    component: () => import('@/pages/other/page404')
  }
]
// 异步路由
export const asyncRoutes = [
  {
    name: 'dashboard',
    path: 'dashboard',
    component: () => import('@/pages/index/children/dashboard'),
    meta: {
      icon: 'dashboard',
      affix: true
    }
  },
  {
    name: 'guide',
    path: 'guide',
    component: () => import('@/pages/index/children/guide/guide'),
    meta: {
      icon: 'guide'
    }
  },
  {
    name: 'permission',
    path: 'permission',
    component: () => import('@/pages/index/children/permission/permission'),
    meta: {
      icon: 'lock',
      roles: 'admin'
    }
  },
  {
    name: 'icons',
    path: 'icons',
    component: () => import('@/pages/index/children/icons/icons'),
    meta: {
      icon: 'icons'
    }
  },
  {
    name: 'components',
    path: 'components',
    component: PageView,
    meta: {
      icon: 'component'
    },
    children: [
      {
        name: 'loading',
        path: 'loading',
        component: () => import('@/pages/index/children/components-demo/loading'),
        meta: {
          icon: 'spinner'
        }
      },
      {
        name: 'dragDemo',
        path: 'dragDemo',
        component: PageView,
        meta: {
          icon: 'move'
        },
        children: [
          {
            name: 'dragDialog',
            path: 'dragDialog',
            component: () => import('@/pages/index/children/components-demo/dragDialog')
          },
          {
            name: 'dragTable',
            path: 'dragTable',
            component: () => import('@/pages/index/children/components-demo/dragTable')
          },
          {
            name: 'dragList',
            path: 'dragList',
            component: () => import('@/pages/index/children/components-demo/dragList')
          }
        ]
      },
      {
        name: 'sticky',
        path: 'sticky',
        component: () => import('@/pages/index/children/components-demo/sticky'),
        meta: {
          icon: 'thumbtack'
        }
      },
      {
        name: 'backTop',
        path: 'backTop',
        component: () => import('@/pages/index/children/components-demo/backTop'),
        meta: {
          icon: 'backtop'
        }
      },
      {
        name: 'numTo',
        path: 'numTo',
        component: () => import('@/pages/index/children/components-demo/numTo'),
        meta: {
          icon: 'number'
        }
      },
      {
        name: 'progressbar',
        path: 'progressbar',
        component: () => import('@/pages/index/children/components-demo/progressbar'),
        meta: {
          icon: 'progressbar'
        }
      },
      {
        name: 'clipboard',
        path: 'clipboard',
        component: () => import('@/pages/index/children/components-demo/clipboard'),
        meta: {
          icon: 'clipboard'
        }
      },
      {
        name: 'editor',
        path: 'editor',
        component: () => import('@/pages/index/children/components-demo/editor'),
        meta: {
          icon: 'editor'
        }
      },
      {
        name: 'markdown',
        path: 'markdown',
        component: () => import('@/pages/index/children/components-demo/markdown'),
        meta: {
          icon: 'markdown'
        }
      },
      {
        name: 'singleMessage',
        path: 'singleMessage',
        component: () => import('@/pages/index/children/components-demo/singleMessage'),
        meta: {
          icon: 'el-icon-message-solid'
        }
      }
    ]
  },
  {
    name: 'excel',
    path: 'excel',
    component: PageView,
    meta: {
      icon: 'excel'
    },
    children: [
      {
        name: 'exportExcel',
        path: 'exportExcel',
        component: () => import('@/pages/index/children/excel/exportExcel')
      },
      {
        name: 'exportSelected',
        path: 'exportSelected',
        component: () => import('@/pages/index/children/excel/exportSelected')
      },
      {
        name: 'importExcel',
        path: 'importExcel',
        component: () => import('@/pages/index/children/excel/importExcel')
      }
    ]
  },
  {
    name: 'zip',
    path: 'zip',
    component: PageView,
    meta: {
      icon: 'zip'
    },
    children: [
      {
        name: 'exportZip',
        path: 'exportZip',
        component: () => import('@/pages/index/children/zip/exportZip')
      }
    ]
  }
]

然后在创建perssion.js,用来调用store里里面定义的路由方法。

import router from '@/router'
import store from '@/store'
import cache from '@/utils/cache'

// 登录验证,权限验证
router.beforeEach((to, from, next) => {
  // 是否需要登录
  if (cache.getToken()) {
    if (to.path === '/login') {
      next('/index')
      // next()
    } else {
      // 是否已有用户信息
      let userInfo = store.state.login.user
      if (userInfo) {
        assessPermission(userInfo.roles, to.meta.roles, next)
      } else {
        store
          .dispatch('login/getUserData')
          .then(res => {
            store.dispatch('routes/generateRoutes').then(addRoutes => {
              console.log(addRoutes)
              router.addRoutes(addRoutes)
              console.log(router)
              next({ ...to, replace: true })
            })
          })
          .catch(err => {
            console.log(err)
            // 可根据错误信息,做相应需求,这里默认token值失效
            window.alert('登录已失效,请重新登录')
            store.dispatch('login/logout').then(() => {
              next({ path: '/login', query: { redirect: to.fullPath } })
            })
          })
      }
    }
  } else {
    if (to.path === '/login') {
      next()
    } else {
      next({ path: '/login', query: { redirect: to.fullPath } })
    }
  }
})

// 验证权限(页面级)
function assessPermission(userRole, pageRole, next) {
  let pass = false
  // 页面无需权限 || 用户是管理员
  if (!pageRole || userRole.indexOf('admin') > -1) pass = true
  // 符合页面的其中一种权限(支持String和Array写法)
  if (typeof pageRole === 'string') {
    if (userRole.indexOf(pageRole) > -1) pass = true
  } else if (Array.isArray(pageRole)) {
    if (pageRole.some(role => userRole.indexOf(role) > -1)) pass = true
  }
  pass ? next() : next('/page401')
}

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • app内的web页面,img路径对,但是不显

    app内的web页面,img路径对,但是不显

  • 如何做下载功能?

    如何做下载功能?

  • 复杂正则表达式,实现思路

    复杂正则表达式,实现思路

  • vue一段简单的代码出现奇怪的问题?

    vue一段简单的代码出现奇怪的问题?

腾讯云代理商
海外云服务器