vue iview实现动态路由和权限验证功能


Posted in Javascript onApril 17, 2018

github上关于vue动态添加路由的例子很多,本项目参考了部分项目后,在iview框架基础上完成了动态路由的动态添加和菜单刷新。为了帮助其他需要的朋友,现分享出实现逻辑,欢迎一起交流学习。

Github地址

iview-dynamicRouter

实现目标

客户端从服务端拿到路由和权限数据后,刷新项目的路由和菜单列表,并进行权限控制。

项目基础

  • 基础框架: iview组件库官方模板项目 iview-admin 的template分支项目,此项目为 iview-admin 的基础框架代码。项目地址:iview-admin 

实现逻辑

动态路由控制加载

一般来说,动态路由控制分为两种:一种是将所有路由数据存储在本地文件中,然后从服务端获取用户的权限信息,在路由跳转时,添加权限判断钩子,如果用户前往的页面不在权限列表内,则禁止跳转。另一种则是本地只存储基本路由,如错误处理页面、无权限控制页面等,而权限路由则从服务器获取,服务器根据用户的权限下发相应的路由数据,客户端利用这些数据进行路由的动态生成和添加,本文采用的是第二种方法。

iview-admin项目将路由分为三种:

  • 不作为Main组件的子页面展示的页面路由,例如login、404、403等错误页面路由;
  • 作为Main组件的子页面展示但是不在左侧菜单显示的路由 otherRouter ,比如首页路由;
  • 作为Main组件的子页面展示并且在左侧菜单显示的路由 appRouter ;

拿到路由数据后,我们主要进行两部分操作,第一部分是遍历数据,利用组件异步加载的方法,加载每个路由节点对应的组件,之后利用 router.addRoutes(routes) 完成路由列表的动态添加;第二部分是因为 iview-admin 框架下的页面标签和面包屑导航,需要遍历appRouter获取路由信息,所以我们也需要将路由数据存入 vuex ,以便全局访问。

需要特别注意的是,如果404页面为静态路由,那么第一次进入页面时,这时动态路由还未加载,找不到路由地址会默认跳转到404错误页,体验很差,所以404路由先不写入路由规则中,和动态路由一起加载。

主要代码实现如下:

数据请求及路由节点生成

//util.js
//生成路由
util.initRouter = function (vm) {
 const constRoutes = [];
 const otherRoutes = [];
 // 404路由需要和动态路由一起注入
 const otherRouter = [{
  path: '/*',
  name: 'error-404',
  meta: {
   title: '404-页面不存在'
  },
  component: 'error-page/404'
 }];
 // 模拟异步请求
 util.ajax('menu.json').then(res => {
  var menuData = res.data;
  util.initRouterNode(constRoutes, menuData);
  util.initRouterNode(otherRoutes, otherRouter);
  // 添加主界面路由
  vm.$store.commit('updateAppRouter', constRoutes.filter(item => item.children.length > 0));
  // 添加全局路由
  vm.$store.commit('updateDefaultRouter', otherRoutes);
  // 刷新界面菜单
  vm.$store.commit('updateMenulist', constRoutes.filter(item => item.children.length > 0));
 });
};
//生成路由节点
util.initRouterNode = function (routers, data) {
 for (var item of data) {
  let menu = Object.assign({}, item);
  menu.component = lazyLoading(menu.component);
  if (item.children && item.children.length > 0) {
   menu.children = [];
   util.initRouterNode(menu.children, item.children);
  }
  //添加权限判断
  meta.permission = menu.permission ? menu.permission : null;
  //添加标题
  meta.title = menu.title ? menu.title : null;
  menu.meta = meta;
 }
};

动态加载组件

//lazyLoading.js
export default (url) =>()=>import(`@/views/${url}.vue`)
Store缓存实现
//app.js
 // 动态添加主界面路由,需要缓存
updateAppRouter (state, routes) {
 state.routers.push(...routes);
 router.addRoutes(routes);
},
// 动态添加全局路由,不需要缓存
updateDefaultRouter (state, routes) {
 router.addRoutes(routes);
},
// 接受前台数组,刷新菜单
updateMenulist (state, routes) {
 state.menuList = routes;
}

最后在main.js中进行调用

//main.js
 mounted () {
 // 调用方法,动态生成路由
 util.initRouter(this);
 }

权限控制

同动态路由实现方法类似,操作权限控制也一般也分为两种,第一种是页面显示时不控制权限,所有的操作,比如按钮全部展现,然后在操作发起时,进行权限判断,如果用户拥有该操作的权限,则通过,否则提醒用户无权限,第二种则是在页面加载的时候,就进行权限判断,无权限的操作不进行显示。本人更喜欢第二种方法,这样不会对用户进行误导,个人认为用户看到的应该就行可操作的,不然点下按钮再提示无权限的感觉一定很不爽。

本项目的思路来源见参考博文,原博主的具体思路是:在路由结构的meta字段中,添加用户操作权限列表,然后注册全局指令,当节点初次渲染时,判断该页面是否存在权限,如果存在,并且传入的参数不在权限列表中,则直接删除该节点。

主要代码实现如下:

在路由数据中添加 permission 字段,存放权限列表

//menu.json,模拟异步请求数据
[
 {
 "path": "/groupOne",
 "icon": "ios-folder",
 "name": "system_index",
 "title": "groupOne",
 "component": "Main",
 "children": [
  {
  "path": "pageOne",
  "icon": "ios-paper-outline",
  "name": "pageOne",
  "title": "pageOne",
  "component": "group/page1/page1",
  "permission":["del"]
  },
  ...
 ]
 }
]

在遍历生成路由节点时,将 permission 字段数据存入路由节点 meta 属性中

//util.js
//生成路由节点
util.initRouterNode = function (routers, data) {
 for (var item of data) {
  ....
  //添加权限判断
  meta.permission = menu.permission ? menu.permission : null;
  ...
 }
};

定义全局命令组件,读取路由 permission 属性值获得权限列表,如果该不权限在权限列表中,则删除节点

//hasPermission.js 

const hasPermission = {
 install (Vue, options) {
  Vue.directive('hasPermission', {
   bind (el, binding, vnode) {
    let permissionList = vnode.context.$route.meta.permission;
    if (permissionList && permissionList.length && !permissionList.includes(binding.value)) {
     el.parentNode.removeChild(el);
    }
   }
  });
 }
};
export default hasPermission;

权限组件使用示例:

<template>
 <div>
  <h1>page1</h1>
  <Button v-hasPermission="'add'">添加</Button>
  <Button v-hasPermission="'edit'">修改</Button>
  <Button v-hasPermission="'del'">删除</Button>
 </div>
</template>

全局注册组件

// main.js
import hasPermission from '@/libs/hasPermission.js';
Vue.use(hasPermission);

这种权限控制方法的优点就是,不管是管理配置还是页面处理逻辑都相对简单,没有很多重复的代码判断和节点处理,在参考对比了网上几种实现方式后,个人比较推荐这一种方法。

页面标签和面包屑导航

在我看来,页面标签和面包屑都属于系统中锦上添花的页面相关控件,提高页面管理的便捷性,在iview官方admin项目中已经实现了这两个组件。所以这个项目中,只是将其进行移植,实现了组件功能,没有深入了解,感兴趣的可以仔细研究。

总结

以上所述是小编给大家介绍的vue iview实现动态路由和权限验证功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery的ajax请求全面了解
Mar 20 Javascript
jquery选择器排除某个DOM元素的方法(实例演示)
Apr 25 Javascript
JavaScript支持的最大递归调用次数分析
Jun 24 Javascript
javascript元素动态创建实现方法
May 13 Javascript
Node.js的npm包管理器基础使用教程
May 26 Javascript
jquery+ajax实现省市区三级联动效果简单示例
Jan 04 Javascript
如何用js判断dom是否有存在某class的值
Feb 13 Javascript
vue2.0 自定义日期时间过滤器
Jun 07 Javascript
JavaScript+H5实现微信摇一摇功能
May 23 Javascript
vuejs实现折叠面板展开收缩动画效果
Sep 06 Javascript
微信小程序局部刷新触发整页刷新效果的实现代码
Nov 21 Javascript
JavaScript监听键盘事件代码实现
Jun 03 Javascript
基于VuePress 轻量级静态网站生成器的实现方法
Apr 17 #Javascript
Vue-cropper 图片裁剪的基本原理及思路讲解
Apr 17 #Javascript
js闭包学习心得总结
Apr 17 #Javascript
Vue使用json-server进行后端数据模拟功能
Apr 17 #Javascript
js实现点击按钮复制文本功能
Jul 20 #Javascript
Element-UI Table组件上添加列拖拽效果实现方法
Apr 14 #Javascript
React中的render何时执行过程
Apr 13 #Javascript
You might like
php中call_user_func函数使用注意事项
2014/11/21 PHP
详谈php中 strtr 和 str_replace 的效率问题
2017/05/14 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
js将当前时间格式转换成时间搓(自写)
2013/09/26 Javascript
Javascript selection的兼容性写法介绍
2013/12/20 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
基于 Node.js 实现前后端分离
2016/04/23 Javascript
JavaScript基础教程——入门必看篇
2016/05/20 Javascript
JS和jQuery通过this获取html标签中的属性值(实例代码)
2017/09/11 jQuery
bootstrap Table实现合并相同行
2019/07/19 Javascript
vue 实现微信浮标效果
2019/09/01 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
2020/09/24 Javascript
详解vue-router的导航钩子(导航守卫)
2020/11/02 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
[50:04]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第二局
2016/02/28 DOTA
[01:09:01]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第一场 10.28
2020/10/28 DOTA
用Python解析XML的几种常见方法的介绍
2015/04/09 Python
Python设计模式编程中解释器模式的简单程序示例分享
2016/03/02 Python
详谈pandas中agg函数和apply函数的区别
2018/04/20 Python
详解Python3.6安装psutil模块和功能简介
2018/05/30 Python
python实现对指定字符串补足固定长度倍数截断输出的方法
2018/11/15 Python
Python之使用adb shell命令启动应用的方法详解
2019/01/07 Python
python仿抖音表白神器
2019/04/08 Python
MNIST数据集转化为二维图片的实现示例
2020/01/10 Python
Django调用支付宝接口代码实例详解
2020/04/04 Python
解决python 执行sql语句时所传参数含有单引号的问题
2020/06/06 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
详解Java中一维、二维数组在内存中的结构
2021/02/11 Python
《只有一个地球》教学反思
2014/02/14 职场文书
公司周年庆典策划方案
2014/05/17 职场文书
缓刑期间思想汇报范文
2014/10/10 职场文书
2019年最新感恩节祝福语(28句)
2019/11/27 职场文书
Nginx使用X-Accel-Redirect实现静态文件下载的统计、鉴权、防盗链、限速等
2021/04/04 Servers
总结Python连接CS2000的详细步骤
2021/06/23 Python
cypress测试本地web应用
2022/06/01 Javascript