欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用VueRouter的addRoutes方法实现动态添加用户的权限路由

程序员文章站 2022-06-24 17:30:25
最近做vue 单页项目涉及到多角色用户权限问题,不同的角色用户拥有不同的功能权限, 不同的功能权限对应的不同的页面 git: https://github.com/p...

最近做vue 单页项目涉及到多角色用户权限问题,不同的角色用户拥有不同的功能权限, 不同的功能权限对应的不同的页面

git: https://github.com/pch1024/dynamicrouter

举个例子:
  角色a =>功能1
     =>功能2
     =>功能3
     
  角色b =>功能1
     =>功能4
     =>功能5

第1步 定义默认路由和动态路由

//动态路由(所有角色的都在这里,我们都做好组件页面了所以我们一定有这个,防君子不防小人)
export const dynamicrouter = [
  { path: '/b', name: 'b', component: pageb },
  { path: '/c', name: 'c', component: pagec },
];

//默认路由(无需登录就可以使用)
const routes = [
  { path: '/', redirect: '/login' },
  { path: '/login', component: pagelogin},
  { path: '/404', component: page404},
  { path: '*', redirect: '/404' },
];

const router = new vuerouter({
  mode: 'history',
  routes, // (缩写) 相当于 routes: routes
});

第2步 登录获取权限规则

当然,登录还要获取token、用户信息等,我们暂时不关注,我们的权限规则需要在多处使用所以我们将它存到vuex里

// vue 组件
<li @click="login(['b'])">
 模拟用户1登录,权限['b'],跳转到页面b
</li>
<li @click="login(['c'])">
 模拟用户2登录,权限['c'],跳转到页面b,(用户2没有页面b权限,强行进入会gun去页面404)
</li>

// 登录模块---------------------------------------------------------
import { mapactions } from "vuex";
export default {
 methods: {
  ...mapactions([
   "set_rolerouterrules"
  ]),
  login(rolerouterrules) {
   // 登录成功,vuex 存储角色路由
   this.set_rolerouterrules(rolerouterrules);
   // 跳转到动态注册b
   this.$router.replace({ path: "/b" });
  }
 }
};

// vuex 对应功能实现-----------------------------------------------
// 引入第1步 定义的dynamicrouter 
import { dynamicrouter } from './router';
// 私有变量
state: {
  isaddroutes: false,
  // 后端返回的原始数据默认存到 localstorage,每次初始化取出来
  rolerouterrules: json.parse(localstorage.getitem('rolerouterrules')),
},
// 公共变量 => 派生私有变量
getters: {
  isaddroutes: state => state.isaddroutes,
  // 根据 rolerouterrules 生成当前角色的动态路由配置数据(addroutes方法可以直接使用的路由数组)
  rolerouter: state => {
    if (state.rolerouterrules) {
      return dynamicrouter.filter(
        router => state.rolerouterrules.indexof(router.name) >= 0,
      );
    } else return null;
  },
},
// 私有方法(同步) => 改变静态变量
mutations: {
  set_isaddroutes: (state, data) => (state.isaddroutes = data), // payload: true/false
  set_rolerouterrules: (state, data) => (state.rolerouterrules = data), // payload: true/false
},
// 公共方法(可异步)=> 调用私有方法
actions: {
  set_isaddroutes({ commit }, data) {
    commit('set_isaddroutes', data);
  },
  set_rolerouterrules({ commit }, data) {
    // 保存到vuex
    commit('set_rolerouterrules', data);
    // 保存到 localstorage,当用户强制刷新浏览器时我们要使用这一份数据初始化 state.rolerouterrules
    localstorage.setitem('rolerouterrules', json.stringify(data));
  },
}

第3步 登录成功跳转权限页面(核心)

基本思路:

  • 所有的路由跳转都要做鉴权,
  • 不是动态路由(也就是默认路由)直接放过,
  • 是动态路由(也就是还未创建的,强行进入会被重定向到404,但依然可以在to.redirectedfrom获取到用户希望进去的路由),检查前端是否有路由权限规则数据
    • 没有,让他去登录页
    • 有,就根据 rolerouterrules 生成当前角色的动态路由配置数据并addroutes添加到真实router,此时通过let path = to.redirectedfrom || to.path; 和 next(path); 再走一遍鉴权(这一次真实router上有它就进页面,还没有就代表这个用户没有这个页面访问权限gun去404)

注意事项:

  • addroutes() 方法一个用户只能使用一次,所以要加一个状态值isaddroutes到vuex里,每次用户进动态路由时检查 addroutes 使用过没有
  • next() 方法没有参数会直接放行,有参数(例如 next({path:'/404'})) 放行后会再次进入router.beforeeach,一不小心就是死循环
import vuex from './vuex';
router.beforeeach((to, from, next) => {
  let path = to.redirectedfrom || to.path;
  // 白名单 放行
  if (whitelist.indexof(path) >= 0) return next();
  // 黑名单
  if (!vuex.getters.rolerouter) return next({ path: '/login' });
  if (!vuex.getters.isaddroutes) {
    console.log('path未注册,存在角色路由,立即注册尝试匹配');
    router.addroutes(vuex.getters.rolerouter);
    vuex.dispatch('set_isaddroutes', true);
    next(path);
  } else {
    console.log('已注册过动态路由,尝试匹配');
    next();
  }
});

第4步 切换不同角色用户

此处有坑, vue router 只提供了 addroutes ,却没有删除和替换方法,所以只能通过强刷新浏览器来重置 vue router,先清空localstorage,在刷新时,初始化的vue router只有默认路由,用户只能去登录页了

还有一种方法我没看懂,感兴趣可以查看:

exit() {
 localstorage.clear();
 window.location.reload();
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。