vue权限路由实现的方法示例总结(3)

关键的代码如下

if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
 store.dispatch('GetUserInfo').then(res => { // 拉取user_info
  const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
  store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
  router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
  next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
  })
 }).catch((err) => {
  store.dispatch('FedLogOut').then(() => {
  Message.error(err || 'Verification failed, please login again')
  next({ path: '/' })
  })
 })

上面的代码就是vue-element-admin的实现

缺点

  • 全局路由守卫里,每次路由跳转都要做判断
  • 菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译
  • 菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,而且路由不一定作为菜单显示,还要多加字段进行标识

菜单与路由分离,菜单由后端返回

菜单的显示标题,图片等需要随时更改,要对菜单做管理功能。

后端直接根据用户权限返回可访问的菜单。

实现

前端定义路由信息(标准的路由定义,不需要加其他标记字段)。

{
 name: "login",
 path: "/login",
 component: () => import("@/pages/Login.vue")
}

name字段都不为空,需要根据此字段与后端返回菜单做关联。

做菜单管理功能的时候,一定要有个字段与前端的路由的name字段对应上(也可以是其他字段,只要菜单能找到对应的路由或者路由能找到对应的菜单就行),并且做唯一性校验。菜单上还需要定义权限字段,可以是一个或多个。其他信息,比如显示标题,图标,排序,锁定之类的,可以根据实际需求进行设计。

还是在全局路由守卫里做判断

function hasPermission(router, accessMenu) {
 if (whiteList.indexOf(router.path) !== -1) {
 return true;
 }
 let menu = Util.getMenuByName(router.name, accessMenu);
 if (menu.name) {
 return true;
 }
 return false;

}

Router.beforeEach(async (to, from, next) => {
 if (getToken()) {
 let userInfo = store.state.user.userInfo;
 if (!userInfo.name) {
 try {
 await store.dispatch("GetUserInfo")
 await store.dispatch('updateAccessMenu')
 if (to.path === '/login') {
  next({ name: 'home_index' })
 } else {
  //Util.toDefaultPage([...routers], to.name, router, next);
  next({ ...to, replace: true })//菜单权限更新完成,重新进一次当前路由
 }
 } 
 catch (e) {
 if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
  next()
 } else {
  next('/login')
 }
 }
 } else {
 if (to.path === '/login') {
 next({ name: 'home_index' })
 } else {
 if (hasPermission(to, store.getters.accessMenu)) {
  Util.toDefaultPage(store.getters.accessMenu,to, routes, next);
 } else {
  next({ path: '/403',replace:true })
 }
 }
 }
 } else {
 if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
 next()
 } else {
 next('/login')
 }
 }
 let menu = Util.getMenuByName(to.name, store.getters.accessMenu);
 Util.title(menu.title);
});

Router.afterEach((to) => {
 window.scrollTo(0, 0);
});
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/37.html