使用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 相关文章推荐
filemanage功能中用到的common.js
Apr 08 Javascript
初学JavaScript_03(ExtJs Grid的简单使用)
Oct 02 Javascript
JavaScript是如何实现继承的(六种方式)
Mar 31 Javascript
jquery 实现回车登录详解及实例代码
Oct 23 Javascript
javascript基本数据类型及类型检测常用方法小结
Dec 14 Javascript
详解Javascript几种跨域方式总结
Feb 27 Javascript
Javascript ES6中数据类型Symbol的使用详解
May 02 Javascript
vue实现商城上货组件简易版
Nov 27 Javascript
用原生 JS 实现 innerHTML 功能实例详解
Apr 03 Javascript
使用vuex解决刷新页面state数据消失的问题记录
May 08 Javascript
微信小程序环境下将文件上传到OSS的方法步骤
May 31 Javascript
Vue管理系统前端之组件拆分封装详解
Aug 23 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
PHP实现防盗链的方法分析
2017/07/25 PHP
Javascript客户端脚本的设计和应用
2006/08/21 Javascript
javascript Select标记中options操作方法集合
2008/10/22 Javascript
jquery.blockUI.js上传滚动等待效果实现思路及代码
2013/03/18 Javascript
jQuery去掉字符串起始和结尾的空格(多种方法实现)
2013/04/01 Javascript
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
jquery实现鼠标滑过小图查看大图的方法
2015/07/20 Javascript
原生JavaScript实现动态省市县三级联动下拉框菜单实例代码
2016/02/03 Javascript
一个字符串中出现次数最多的字符 统计这个次数【实现代码】
2016/04/29 Javascript
原生js仿浏览器滚动条效果
2017/03/02 Javascript
js指定步长实现单方向匀速运动
2017/07/17 Javascript
d3绘制基本的柱形图的实现代码
2018/12/12 Javascript
JavaScript解析机制与闭包原理实例详解
2019/03/08 Javascript
中级前端工程师必须要掌握的27个JavaScript 技巧(干货总结)
2019/09/23 Javascript
使用Karma做vue组件单元测试的实现
2020/01/16 Javascript
Python实现的tab文件操作类分享
2014/11/20 Python
Python的Django框架中设置日期和字段可选的方法
2015/07/17 Python
python实现校园网自动登录的示例讲解
2018/04/22 Python
Python3 itchat实现微信定时发送群消息的实例代码
2019/07/12 Python
Django框架之DRF 基于mixins来封装的视图详解
2019/07/23 Python
Python递归函数 二分查找算法实现解析
2019/08/12 Python
python爬虫泛滥的解决方法详解
2020/11/25 Python
Selenium获取登录Cookies并添加Cookies自动登录的方法
2020/12/04 Python
HTML5新增属性data-*和js/jquery之间的交互及注意事项
2017/08/08 HTML / CSS
Fossil加拿大官网:化石手表、手袋、首饰及配饰
2019/04/23 全球购物
函数只定义了一次, 调用了一次, 但编译器提示非法重定义了-什么问题?
2014/10/03 面试题
应届生财务管理求职信
2013/11/06 职场文书
机械制造毕业生求职信
2014/03/03 职场文书
高中运动会广播稿
2014/09/16 职场文书
学生检讨书如何写
2014/10/30 职场文书
群众路线教育实践活动实施方案
2014/10/31 职场文书
2014年人力资源部工作总结
2014/11/19 职场文书
幼儿园教学工作总结2015
2015/05/12 职场文书
Python3 使用pip安装git并获取Yahoo金融数据的操作
2021/04/08 Python
浅谈Python项目的服务器部署
2021/04/25 Python
Qt自定义Plot实现曲线绘制的详细过程
2021/11/02 Python