使用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 相关文章推荐
ExtJS 2.0实用简明教程之应用ExtJS
Apr 29 Javascript
js window.onload 加载多个函数的方法
Nov 02 Javascript
jquery插件制作 表单验证实现代码
Aug 17 Javascript
JavaScript原生对象之Number对象的属性和方法详解
Mar 13 Javascript
Jquery基础教程之DOM操作
Aug 19 Javascript
JavaScript设计模式经典之工厂模式
Feb 24 Javascript
功能强大的Bootstrap效果展示(二)
Aug 03 Javascript
在vue-cli中组件通信的方法
Dec 16 Javascript
把vue-router和express项目部署到服务器的方法
Feb 21 Javascript
微信小程序实现跑马灯效果完整代码(附效果图)
May 30 Javascript
vue+element项目中过滤输入框特殊字符小结
Aug 07 Javascript
在Webpack中用url-loader处理图片和字体的问题
Apr 28 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中照片旋转 (orientation) 问题的正确处理
2017/02/16 PHP
PHP绕过open_basedir限制操作文件的方法
2018/06/10 PHP
Javascript的匿名函数小结
2009/12/31 Javascript
一张表格告诉你windows.onload()与$(document).ready()的区别
2014/05/16 Javascript
简介可以自动完成UI的AngularJS工具angular-smarty
2015/06/23 Javascript
js中unicode转码方法详解
2015/10/09 Javascript
jQuery使用deferreds串行多个ajax请求
2016/08/22 Javascript
Jquery 整理元素选取、常用方法一览表
2016/11/26 Javascript
jQuery编写设置和获取颜色的插件
2017/01/09 Javascript
JS正则表达式验证账号、手机号、电话和邮箱是否合法
2017/03/08 Javascript
yii form 表单提交之前JS在提交按钮的验证方法
2017/03/15 Javascript
JavaScript实现反转字符串的方法详解
2017/04/27 Javascript
Nodejs之http的表单提交
2017/07/07 NodeJs
浅谈Vue.js 1.x 和 2.x 实例的生命周期
2017/07/25 Javascript
javascript 面向对象实战思想分享
2017/09/07 Javascript
vue实现登录后页面跳转到之前页面
2018/01/07 Javascript
Vue中的异步组件函数实现代码
2018/07/20 Javascript
angular 服务的单例模式(依赖注入模式下)详解
2018/10/22 Javascript
微信小程序入口场景的问题集合与相关解决方法
2019/06/26 Javascript
解决Antd Table组件表头不对齐的问题
2020/10/27 Javascript
Pyramid将models.py文件的内容分布到多个文件的方法
2013/11/27 Python
粗略分析Python中的内存泄漏
2015/04/23 Python
Python socket套接字实现C/S模式远程命令执行功能案例
2018/07/06 Python
Python实现二叉树的常见遍历操作总结【7种方法】
2019/03/06 Python
在VS2017中用C#调用python脚本的实现
2019/07/31 Python
基于python判断目录或者文件代码实例
2019/11/29 Python
css3发光搜索表单分享
2014/04/11 HTML / CSS
英国二手物品交易网站:Preloved
2017/10/06 全球购物
武汉瑞得软件笔试题
2015/10/27 面试题
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
2013/04/11 面试题
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?
2016/08/18 面试题
秘书专业自荐信范文
2013/12/26 职场文书
父亲生日宴会答谢词
2014/01/10 职场文书
个人遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
GO中sync包自由控制并发示例详解
2022/08/05 Golang