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


Posted in Javascript onJune 03, 2019

最近做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只有默认路由,用户只能去登录页了

还有一种方法我没看懂,感兴趣可以查看:https://github.com/vuejs/vue-router/issues/1234

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

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

Javascript 相关文章推荐
动态添加js事件实现代码
Mar 12 Javascript
javascript 读取xml,写入xml 实现代码
Jul 10 Javascript
Javascript的时间戳和php的时间戳转换注意事项
Apr 12 Javascript
在JS数组特定索引处指定位置插入元素的技巧
Aug 24 Javascript
编程语言JavaScript简介
Oct 16 Javascript
jQuery实现新消息闪烁标题提示的方法
Mar 11 Javascript
Javascript中的作用域和上下文深入理解
Jul 03 Javascript
用jQuery实现圆点图片轮播效果
Mar 19 Javascript
javascript获取指定区间范围随机数的方法
Sep 08 Javascript
vue中轮训器的使用
Jan 27 Javascript
JavaScript中.min.js和.js文件的区别讲解
Feb 13 Javascript
JavaScript大数相加相乘的实现方法实例
Oct 18 Javascript
使用watch在微信小程序中实现全局状态共享
Jun 03 #Javascript
深入理解JS异步编程-Promise
Jun 03 #Javascript
模块化react-router配置方法详解
Jun 03 #Javascript
react 组件传值的三种方法
Jun 03 #Javascript
angular使用md5,CryptoJS des加密的方法
Jun 03 #Javascript
Node.js 的 GC 机制详解
Jun 03 #Javascript
微信小程序蓝牙连接小票打印机实例代码详解
Jun 03 #Javascript
You might like
从零开始学YII2框架(二)通过 Composer 安装扩展插件
2014/08/20 PHP
php利用递归实现删除文件目录的方法
2016/09/23 PHP
php常用字符串查找函数strstr()与strpos()实例分析
2019/06/21 PHP
php引用和拷贝的区别知识点总结
2019/09/23 PHP
让innerHTML的脚本也可以运行起来
2006/07/01 Javascript
一个选择最快的服务器转向代码
2009/04/27 Javascript
javascript 四则运算精度修正函数代码
2010/05/31 Javascript
file控件选择上传文件确定后触发的js事件是哪个
2014/03/17 Javascript
JavaScript监听和禁用浏览器回车事件实例
2015/01/31 Javascript
JavaScript合并两个数组并去除重复项的方法
2015/06/13 Javascript
JS+DIV+CSS排版布局实现美观的选项卡效果
2015/10/10 Javascript
jQuery使用deferreds串行多个ajax请求
2016/08/22 Javascript
微信小程序开发一键登录 获取session_key和openid实例
2016/11/23 Javascript
详解Python中logging日志模块在多进程环境下的使用
2016/12/26 Javascript
Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定示例
2017/01/22 Javascript
JavaScript简介_动力节点Java学院整理
2017/06/26 Javascript
vue2.0 移动端实现下拉刷新和上拉加载更多的示例
2018/04/23 Javascript
原生JS实现的简单小钟表功能示例
2018/08/30 Javascript
微信小程序用户授权,以及判断登录是否过期的方法
2019/05/10 Javascript
使用konva和vue-konva库实现拖拽滑块验证功能
2020/04/27 Javascript
以Python的Pyspider为例剖析搜索引擎的网络爬虫实现方法
2015/03/30 Python
Python使用urllib2模块抓取HTML页面资源的实例分享
2016/05/03 Python
R vs. Python 数据分析中谁与争锋?
2017/10/18 Python
Tensorflow训练MNIST手写数字识别模型
2020/02/13 Python
Python reversed反转序列并生成可迭代对象
2020/10/22 Python
Python 使用SFTP和FTP实现对服务器的文件下载功能
2020/12/17 Python
检测用户浏览器是否支持CSS3的方法
2009/08/29 HTML / CSS
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
毕业设计计划书
2014/01/09 职场文书
体育专业自荐书
2014/05/29 职场文书
党的群众路线教育实践活动查摆问题及整改措施
2014/10/10 职场文书
2015年禁毒宣传活动总结
2015/03/25 职场文书
使用pycharm运行flask应用程序的详细教程
2021/06/07 Python
python基础之类方法和静态方法
2021/10/24 Python
如何在Python中妥善使用进度条详解
2022/04/05 Python
使用Ajax实现进度条的绘制
2022/04/07 Javascript