前情回顾:
如果对vue路由部分还不是很熟悉的小伙伴,建议可以先去了解一下,或者看一下我的这两篇笔记:
开始~~
文件:项目目录/src/router/index.js
1、动态路由分析
在项目目录/src/router/index.js
文件里,代码export const asyncRoutes
开始的部分的整个结构体,就是动态路由部分。
- 这部分定义的
asyncRoutes
,就是动态路由,用户可用路由条数,是计算出来的 - 然后将计算出来的当前用户路由,渲染到菜单栏上
permission.js
进行鉴权计算的,在main.js
中引用了的- 权限:页面级、路由器权限:不同权限的用户,登录进来,看到的侧边栏是不一样的、不同页面
- 区分用户可访问的范围
// 这部分定义的asyncRoutes,就是动态路由,用户可用路由条数,是计算出来的
// 然后将计算出来的当前用户路由,渲染到菜单栏上
// permission.js进行鉴权计算的,在main.js中引用了的
// 权限:页面级、路由器权限:不同权限的用户,登录进来,看到的侧边栏是不一样的、不同页面
// 区分用户可访问的范围
export const asyncRoutes = [
{
path: '/permission',//访问路径
component: Layout,//放置一个layout组件
redirect: '/permission/page',// 重定向到了自己的二级路由,在下面有配置
alwaysShow: true, // 在根菜单中显示
name: 'Permission',
meta: { //路由元信息
title: 'permission',//菜单中标题
icon: 'lock',//菜单中图标
// 权限就是靠roles区分的
//本项目就两个角色:admin、editor,可根据自己实际调整
roles: ['admin', 'editor'] // 可见的角色,数组
},
children: [
{
//二级路由的path不要带‘/’
path: 'page',//二级路由路径,完整:/permission/page
component: () => import('@/views/permission/page'),//对应组件
name: 'PagePermission',//路由名字
meta: {
title: 'pagePermission',//标题
roles: ['admin'] // 可访问、可见的角色
}
},
{
path: 'directive',
component: () => import('@/views/permission/directive'),
name: 'DirectivePermission',
meta: {
title: 'directivePermission'
// 二级路由权限,必须大于等于一级路由权限
// 如:一级路由admin可访问、二级设置editor可访问
// edtior根本没有机会看到二级
// 如果不设置角色roles,则表示:此页面不需要权限校验
}
},
{
path: 'role',
component: () => import('@/views/permission/role'),
name: 'RolePermission',
meta: {
title: 'rolePermission',
roles: ['admin']
}
}
]
},
{
path: '/icon',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/icons/index'),
name: 'Icons',
meta: { title: 'icons', icon: 'icon', noCache: true }
}
]
},
2、permission.js鉴权逻辑分析
在项目目录/src/permission.js
文件里
该文件详细处理了鉴权过程的全部逻辑,
先看看流程图:
对比流程图,看代码分析
// 引入vue
import router from './router'
// 引入vuex仓库
import store from './store'
// 引入element-ui的提示组件
import { Message } from 'element-ui'
// 引入进度条、进度条风格
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
// 引入从cookie中获取 Token工具,登录后,token在cookie中
import { getToken } from '@/utils/auth'
// 引入从 获取title工具,用于切换的时候,titile变化
import getPageTitle from '@/utils/get-page-title'
// 配置进度条
NProgress.configure({ showSpinner: false })
// 配置白名单:登录页面(不需要登录即可访问)
const whiteList = ['/login', '/auth-redirect']
// 全局前置路由守卫,核心逻辑都在守卫中
router.beforeEach(async(to, from, next) => {
// 开始进度条
NProgress.start()
//设置页面标题
document.title = getPageTitle(to.meta.title)
// 从cookie中获取token
const hasToken = getToken()
// 如果有token 说明已经登录了
if (hasToken) {
if (to.path === '/login') {
// 如果已经登录,又访问了登录页
next({ path: '/' })//定向放行到后台首页面
NProgress.done() //进度条结束
} else {//你登录了,你去的除了登录页之外的页面
// 在vuex中的仓库store中看你的权限(存在,且不为空)
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) { //权限roles存在,且不为空
next() //放行
} else { //如果没有角色信息,比如刷新了浏览器
try {
//用vuex发起获取用户信息请求
const { roles } = await store.dispatch('user/getInfo')
// 用获取到的用户信息中的权限,传入VUEX方法,生成路由规则
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// console.log("accessRoutes",accessRoutes)
// 将生成的当前用户的路由规则,添加到路由器,addRoutes方法,在user.js中
router.addRoutes(accessRoutes)
// 放行
next({ ...to, replace: true })
} catch (error) {
// 获取权限过程异常,就清除登录状态
await store.dispatch('user/resetToken')
// 提示错误
Message.error(error || 'Has Error')
// 跳转到登录页面
next(`/login?redirect=${to.path}`)
NProgress.done()//进度条结束
}
}
}
} else {//如果没有token
// 你访问的路径是不是白名单路径
if (whiteList.indexOf(to.path) !== -1) {
// 是白名单,就放行
next()
} else {
// 如果不在白名单,就跳转登录页
next(`/login?redirect=${to.path}`)
NProgress.done()//进度条结束
}
}
})
// 全局后置路由守卫,就干了一件事,结束进度条
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
根据 获取到的用户信息中的权限,传入VUEX方法,生成路由规则,打印结果:
点击登录,发了两次请求:
第一次:先发登录请求,校验用户名密码,成功的话,返回token
第二次:用token,获取用户信息(权限、用户名、头像等等)