手机版

vue权限路由实现方法示例概述

时间:2021-08-30 来源:互联网 编辑:宝哥软件园 浏览:

使用全局路由保护

实现

前端定义路由,并在路由上标记相应的权限信息

const routerMap=[{ path : '/permission ',component: Layout,redirect : '/permission/index ',alwaysShow: true,//将始终显示根菜单meta : { title : ' permission ',icon: 'lock ',role 3360[' admin ',' editor'] //您可以在根nav }中设置角色,children :[{ path 3: ' page ',component :()] meta : { title : ' directive permission '//如果不设置角色,则表示:此页面不需要权限}}]]全局路由守护判断用户是否每次都登录过,如果没有则跳转到登录页面。 如果已经登录(已经获取后台返回的用户权限信息(如角色)),判断用户是否有权限访问当前路由(根据路由名称从所有路由中查找对应的路由,判断用户是否有在路由上标注的权限信息(例如上面的roles 3360[' admin ',' editor '))。未经允许,跳转到预定义的界面(403,404等。).

这样可以直接通过route生成菜单(也显示没有用户权限的菜单,只有用户点击跳转时才会判断权限),也可以在用户登录后根据用户权限过滤路由生成菜单(菜单需要保存在vuex中)。

目前,iview-admin仍然使用这种方法

劣势

装载所有路线。如果路由多,用户不能访问所有路由,会影响性能。在全局路由守护中,每一次路由跳转都必须由权威来判断。菜单信息写在前端。要更改显示文本或权限信息,有必要重新编译菜单并将其与路线关联。定义路线时,会添加菜单显示标题和图标等信息,路线不一定显示为菜单。应该添加更多的字段来标识登录页面与主应用程序的分离

鉴于前一种实现的缺点,登录页面和主应用可以放在不同的页面上(不在同一个vue应用实例中)。

实现

登录成功后,执行页面跳转(真正的页面跳转,不是路由跳转),将用户权限转移到主应用所在的页面。在主应用初始化之前,根据用户权限对路由进行过滤,过滤后的路由作为vue的实例化参数,而不是像前面那样转移所有路由,也不需要在全局路由守护中判断权限。

劣势

需要做页面跳转,不是纯单页的应用菜单信息都写在前端。要更改显示文本或权限信息,您需要重新编译菜单并将其与路线关联起来。定义路线时,您还可以添加菜单显示标题、图标和其他信息,路线不一定显示为菜单,但您需要添加更多字段来识别它。使用添加路由动态挂载路由。

AddRoutes允许在应用程序初始化后动态装载路由。有了这种新的姿态,就不需要像以前那样在应用程序初始化期间过滤路由。

实现

当应用程序初始化时,首先挂载不需要权限控制的路由,如登录页面、404和其他错误页面。

有一个问题,应该在何时何地调用addRoutes

登录后,获取用户的权限信息,过滤有权限访问的路由,然后调用addRoutes添加路由。这种方法是可行的。但是不可能每次进入应用都登录,刷新浏览器时用户还要重新登录。

因此,在全局路由保护中仍应调用添加路由

从""导入路由器/路由器”从导入存储"。/store '从' element-ui '导入{ Message } '从' n progress '导入n进度/从' n progress '导入n进度/n进度。CSS '/进度条样式从“@/utils/auth”/getToken从cookien progress导入{ getToken }。configure({ show spinner 3360 false })//npprogress Configuration//permission只是函数hasPermission(角色,permissionRoles){ if(角色。索引of(' admin ')=0)返回true //管理员权限直接传递if(!权限角色)返回真实的返回角色。一些(角色=permissionRoles。indexof(角色)=0)} const白名单=['/login ','/authredirect']//无重定向白名单router.beforeEach((to,from,next)={ nprogress。start()//start进度条if (getToken()) { //判断是否有令牌/*有token */if(to。path=='='/log in '){ next({ path : '/})n progress。done()//如果当前页面为判断当前用户是否已拉取完用户信息信息store.dispatch('GetUserInfo ').然后(res={ //拉取user _ info const roles=RES . data。角色//注释:角色必须是数组!如: ['编辑器','开发者']商店。调度('生成路由' { roles }).然后(()={ //根据角色权限生成可访问的路由表路由器。添加路线(商店。吸气器。addrouters)//动态添加可访问路由表下一个({ 0.to,replace: true }) //hack方法确保添加路由已完成,将替换:设置为没错,以便导航不会留下历史记录}) })。catch((err)={ store。调度(' FedLogout ').然后(()={ Message.error(err ||)验证失败,请重新登录)下一步({ path : '/' })})})else {//没有动态改变权限的需求可直接下一个()删除下方权限判断if(hasPermission(store。getter的角色。梅塔。roles)){ next()//} else { next({ path : '/401 ',replace: true,query : { nogo back : true } })}//可删} } } else {/*没有标记*/if(白名单。索引属于(到.路径)!==-1) { //在免登录白名单,直接进入next() } else { next('/login') //否则全部重定向到登录页npprogress。done()//如果当前页面是登录后不会触发每个钩子,所以手动处理它} } })路由器。在.之后每个(()={ npprogress。done()//完成进度条})关键的代码如下

if(商店。吸气器。角色。长度===0){//判断当前用户是否已拉取完用户信息信息store.dispatch('GetUserInfo ').然后(res={ //拉取user _ info const roles=RES . data。角色//注释:角色必须是数组!如: ['编辑器','开发者']商店。调度('生成路由' { roles }).然后(()={ //根据角色权限生成可访问的路由表路由器。添加路线(商店。吸气器。addrouters)//动态添加可访问路由表下一个({ 0.to,replace: true }) //hack方法确保添加路由已完成,将替换:设置为没错,以便导航不会留下历史记录}) })。catch((err)={ store。调度(' FedLogout ').然后(()={ Message.error(err ||)验证失败,请重新登录)下一步({ path: '/' }) })上面的代码就是vue-元素-管理的实现

缺点

全局路由守卫里,每次路由跳转都要做判断菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,而且路由不一定作为菜单显示,还要多加字段进行标识菜单与路由分离,菜单由后端返回

菜单的显示标题,图片等需要随时更改,要对菜单做管理功能。

后端直接根据用户权限返回可访问的菜单。

实现

前端定义路由信息(标准的路由定义,不需要加其他标记字段)。

{ name: 'login ',path: '/login ',组件:()=import(' @/page/log in。vue’)}名称字段都不为空,需要根据此字段与后端返回菜单做关联。

做菜单管理功能时,必须有一个字段对应前端路由的名称字段(也可以是其他字段,只要菜单能找到对应的路由或者路由能找到对应的菜单),并且必须做唯一性检查。菜单还需要定义一个或多个权限字段。其他信息,如显示标题、图标、排序、锁定等。可根据实际需要设计。

还是你在全局路由守护中判断

函数hasPermission(路由器,访问菜单){ if(白名单.索引Of(路由器.路径)!==-1) {返回true} let menu=Util . GetMenuByname(router . name,AccessMenu);if (menu.name) {返回true}返回false}Router.beforeEach(async (to,from,next)={ if (getToken()) {让userInfo=store . state . user . userInfo;if(!userInfo.name) {尝试{ await store . dispatch(' GetUserInfo ')await store . dispatch(' updateAccessMenu ')if(to . path=='/' log in '){ next({ name : ' home _ index ' })else {//util . todefaultpage([.路由器],to.name,router,next);下一个({ 0.to,replace : true })//更新菜单权限,重新进入当前路由}} Catch (e) {If(白名单。(到)的索引。路径)!==-1) {//在免登录白名单中,直接转到next()} else { next('/log in ')} } else { if(to。path==='/' log in '){ next({ name : ' home _ index ' })} else { if(拥有权限(to,store . geters . accessmenu)){ Util . todefaultpage(store . geters . accessmenu,to,routes,next);} else { next({ path: '/403 ',replace : true })} } } else { if(白名单.索引Of(to.path)!==-1) {//直接转到next()} else { next('/log in ')} } let menu=util . getmenubname(to。name,store . getter . accessmenu);util . title(menu . title);});router . after each((to)={ window . scroll to(0,0);});上面的代码是vue-quasar-admin的实现。因为没有使用addRoutes,所以每次路由跳转都要判断权限,这里的判断也很简单,因为菜单名称与路由名称一一对应,后端返回的菜单已经经过权限过滤,所以如果根据路由名称找不到对应的菜单,就说明用户是否有访问权限。

如果有许多路由,则在初始化应用程序时,只能装载不需要权限控制的路由。获取后端返回的菜单后,根据菜单与路由的对应关系,过滤掉可访问的路由,通过addRoutes动态挂载。

劣势

菜单需要与路线一一对应。前端新增功能,需要通过菜单管理功能新增菜单。如果菜单配置不正确,应用程序无法正常使用全局路由保护,必须判断每一次路由跳转。菜单和路线完全从后端返回

从后端返回菜单是可行的,但是从后端返回路线呢?看看路由的定义

{name:' login ',path:'/login ',component 3360()=import(' @/pages/log in . vue ')}如果后端直接返回,

{'name' :' login ',' path' :'/login ',' component ' : '()=import(' @/pages/log in . vue ')' }这是什么鬼东西?显然是行不通的。()=import('@/pages/Login.vue ')如果前端没有出现此代码,webpack将不会编译和打包Login.vue。

实现

前端统一定义路由组件,例如

const Home=()=import('./pages/home . vue’;const UserInfo=()=import('./pages/UserInfo . vue’);导出默认{ home: Home,user info : user info };路由组件被定义为这种键值结构。

后端返回格式

[{name:' home ',path:'/',component3360' home'},{name:' home ',path:'/userinfo ',component3360' userinfo'}]在通过addRoutes动态挂载后端返回路由之前,需要对数据进行处理。

至于菜单要不要和路线分开,怎么对应,可以根据实际需要来处理。

如果有嵌套路由,在设计后端函数时要注意添加相应的字段。前端获得的数据应该进行相应的处理。

劣势

在全局路由保护中,每一次路由跳转都必须被判断。前端和后端对配合的要求更高。不要使用全局路由保护

前面几种方式,除了登录页与主应用分离,每次路由跳转,都在全局路由守卫里做了判断。

实现

应用初始化的时候只挂载不需要权限控制的路由

const construction map=[{ name : ' log in ',path: '/login ',component :()=import(' @/pages/log in。vue ')},{ path: '/404 ',组件:()=import(' @/pages/page 404。vue ')},{ path: '/init ',组件:()=import(' @/pages/init。vue ')},{ path: ' * '导出默认约束映射;从“Vue”导入Vue从“vue路由器”导入路由器;从""导入ConstantRouterMap ./路由器;使用路由器;导出默认新路由器({ //mode: 'history ',//需要服务支持scrolbehavior :()=({ y : 0 }),routes : constantrotermap });登录成功后跳到/路由

提交表单(formName){ let _ this=this;这个$refs[formName].验证(有效={如果(有效){ _ this .$商店。派单(' loginyusername ',{ name:_this.ruleForm2.name,pass:_this.ruleForm2.pass }).然后(()={ _this .$路由器。push({ path : '/' })})else { return false;} });}因为当前没有/路由,会跳到/404

模板h 1404/h1/templatescriptexport默认{ name:'page404 ',已装载(){ if(!这个$store.state.isLogin){ this .$路由器。替换({ path : '/log in ' });返回;} if(!这个$store.state.initedApp){ this .$路由器。替换({ path : '/init ' });return } }}/script404组件里判断已经登录,接着判断应用是否已经初始化(用户权限信息,可访问菜单,路由等是否已经从后端取得)。没有初始化则跳转到/init路由

模板' div/div/templatescript从导入{ GetAccessMenulist }./mock/menu ';从导入组件./路由器/路由器组件。js ';导出默认的{异步装入(){ if(!这个$store.state.isLogin) { this .$路由器。push({ path : '/log in ' });返回;} if(!这个$商店。国家。inite dapp){ const loading=this .$loading({ lock: true,text: '初始化中,spinner: 'el-icon-loading ',background: 'rgba(0,0,0,0.7)' });let menu=wait GetaccessMenulist();//模拟从后端获取定义变量路由器=[.菜单];for(let router of routers){ let component=components[router。组件];router.component=component}这个$router.addRoutes(路由器);这个$商店。调度(' SetAccessMenuList ',菜单)。然后(()={正在加载。close();这个$路由器。替换({ path : '/' });});返回;} else { this .$路由器。替换({ path : '/' });} }};/scriptinit组件里判断应用是否已经初始化(避免初始化后,直接从地址栏输入地址再次进入当前组件)。

如果已经初始化,跳转/路由(如果后端返回的路由里没有定义次路由,则会跳转404)。

没有初始化,则调用远程接口获取菜单和路由等,然后处理后端返回的路由,将成分赋值为真正的组件,接着调用添加路由挂载新路由,最后跳转/路由即可。菜单的处理也是在此处,看实际需求。

实现例子

缺点

在404页面做了判断,感觉比较怪异多引入了一个初始化页面组件总结

比较推荐后面两种实现方式。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

版权声明:vue权限路由实现方法示例概述是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。