乐趣区

你可能不清楚的 Vue Router 深度用法(一)

Vue Router 简单易上手,能实现大部分的需求。但是,如果在项目里需要更细致的控制路由,以实现与其同步的效果,就需要挖掘其文档里没详细提及的内容。第一章为路由元信息用途挖掘。
路由元信息用途
(1)验证用户身份,定义用户权限能访问的页面
大部分项目,除了登录页、重置密码页、用户协议页以外,页面都需要验证用户身份进行访问。使用 Vue Router 可以配合后端进行双重验证。

(登录)验证身份方法:
1、给需要验证的路由对象添加 meta 字段,里面自定义一个代表验证的字段:
const router = new VueRouter({
routes: [
{
path: ‘/foo’,
component: Foo,
children: [
{
path: ‘bar’,
component: Bar,
meta: {
requiresAuth: true // 添加该字段,表示进入这个路由是需要登录的
}
}
]
}
]
})
2、在全局导航钩子里验证 requiresAuth 字段:
注意事项:

使用 beforeEach 在路由变化前验证。验证原理是在跳转前,访问目标路由对象的 requiresAuth 字段判断是否需要验证用户身份,如为是,检测是否有保存用户信息(即用户登录成功后前端保存的信息,例如 token)
每个路由都有一个 $route.matched 数组,包含当前路由的父级路由对象和当前路由对象,在组件中可以通过 this.$route.matched 访问
beforeEach 的 to 参数即目标路由对象 $route,to.matched 即是它的路由数组
因此,使用 some 方法,只要路由数组里的任意路由对象需要验证身份,即进行验证
验证成功跳转正确页面;失败则跳到登录页,将目标地址附在 url 的 query 里,登录成功就跳转到目标地址

router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) {// 没登录
next({
path: ‘/login’,
query: {redirect: to.fullPath}
})
} else {
next() // 确保一定要调用 next()
}
} else {
next() // 确保一定要调用 next()
}
})
3、拦截 http 请求,验证用户身份
为了防止本地保存的 token 过期,需要拦截 http 请求,为每次请求头加上 token,然后拦截 http 响应,根据响应内容判断是否需要跳回登录页面重新登录。使用 axios 的方法如下:
// http request 拦截器
axios.interceptors.request.use(
config => {
if (auth.loggedIn()) {// 判断是否存在 token,如果存在的话,则每个 http header 都加上 token
config.headers.Authorization = `token ${auth.loggedIn()}`;
}
return config;
},
err => {
return Promise.reject(err);
});

// http response 拦截器

axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// Unauthorized
// 返回 401 清除 token 信息并跳转到登录页面
auth.clear();
router.replace({
path: ‘login’,
query: {
redirect: router.currentRoute.fullPath
}
})
}
}
return Promise.reject(error.response.data) // 返回接口返回的错误信息
});

前端查看权限,也是配合后端进行某些页面的隐藏显示功能。一般应用于综合的办公系统,由 IT 部分配账号,不同部门的人只能看到自己负责的内容,例如行政部不会看到财务数据页面。
实现方法:

前端路由每个页面的 meta 对象添加 level 字段,设置 0 ~ n 级别
登录成功,后台返回用户 token 的同时,返回其所属的 level 字段
组件代码比较目标页面的 level 与用户 level,只显示目标 level 小于等于用户 level 的页面
全局导航钩子 beforeEach 里比较目标页面的 level 与用户 level,小于等于目标 level 则正确跳转,反之取消跳转并提示权限不足

上面第 4 步是为了防止用户直接在浏览器输入目标地址

(2)其他内容控制
可以控制显示路由固定的搭配,例如某个路由地址的 title 是固定的字符串、固定的欢迎语、固定的 favicon 等。在组件里通过 this.$route.meta.xxx 访问。
const router = new VueRouter({
routes: [
{
path: ‘/foo’,
component: Foo,
children: [
{
path: ‘bar’,
component: Bar,
meta: {
title: ‘ 标题 ’,
message: ‘ 欢迎您 ’,
requiresAuth: true // 添加该字段,表示进入这个路由是需要登录的
}
}
]
}
]
})

退出移动版