使用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 相关文章推荐
javascript IE中的DOM ready应用技巧
Jul 23 Javascript
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
Oct 20 Javascript
基于jquery tab切换(防止页面刷新)
May 23 Javascript
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 Javascript
jQuery实用基础超详细介绍
Apr 11 Javascript
批量实现面向对象的实例代码
Jul 01 Javascript
半个小时学json(json传递示例)
Dec 25 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
Feb 16 Javascript
微信小程序学习笔记之本地数据缓存功能详解
Mar 29 Javascript
VScode格式化ESlint方法(最全最好用方法)
Sep 10 Javascript
Vue路由的模块自动化与统一加载实现
Jun 05 Javascript
在vue中动态修改css其中一个属性值操作
Dec 07 Vue.js
使用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
星际争霸, 教主第一视角, ZvT经典龙蛇演义
2020/03/02 星际争霸
一个简单且很好用的php分页类
2013/10/26 PHP
PHP微信开发之根据用户回复关键词\位置返回附近信息
2016/06/24 PHP
php中get_magic_quotes_gpc()函数说明
2017/02/06 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
IE6中使用position导致页面变形的解决方案(js代码)
2011/01/09 Javascript
尝试在让script的type属性等于text/html
2013/01/15 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
2014/10/17 Javascript
JS日期对象简单操作(获取当前年份、星期、时间)
2016/10/26 Javascript
js实现登录验证码
2016/12/22 Javascript
JavaScript控制输入框中只能输入中文、数字和英文的方法【基于正则实现】
2017/03/03 Javascript
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例
2017/04/13 Javascript
微信小程序实现红包功能(后端PHP实现逻辑)
2018/07/11 Javascript
javascript this指向相关问题及改变方法
2020/11/19 Javascript
微信小程序自定义胶囊样式
2020/12/27 Javascript
[02:41]DOTA2英雄基础教程 冥魂大帝
2014/01/16 DOTA
[40:05]LGD vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
使用PYTHON创建XML文档
2012/03/01 Python
详细解析Python当中的数据类型和变量
2015/04/25 Python
解密Python中的描述符(descriptor)
2015/06/03 Python
Python的Django框架中URLconf相关的一些技巧整理
2015/07/18 Python
python简单贪吃蛇开发
2019/01/28 Python
python实现回旋矩阵方式(旋转矩阵)
2019/12/04 Python
Python HTMLTestRunner库安装过程解析
2020/05/25 Python
如何编写python的daemon程序
2021/01/07 Python
如何在C# winform中异步调用web services
2015/09/21 面试题
final, finally, finalize的区别
2012/03/01 面试题
心理学专业大学生职业生涯规划范文
2014/02/19 职场文书
物业管理工作方案
2014/05/10 职场文书
大学迎新标语
2014/06/26 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
2015年党支部书记工作总结
2015/05/21 职场文书
承诺书的内容有哪些,怎么写?
2019/06/21 职场文书
解决Golang中ResponseWriter的一个坑
2021/04/27 Golang
MySQL中distinct和count(*)的使用方法比较
2021/05/26 MySQL
Golang 并发下的问题定位及解决方案
2022/03/16 Golang