在这个前端技术迭代迅速的时代,单页面应用开发中,路由守卫已经是非常常见也是必备的需求,为了控制使用者在各种状态下的路由页面跳转,例如:是否登录,是否有路由权限等等,今天就记录一下在各种登录状态下路由配置和路由守卫。
Vue Router官方文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
页面跳转场景:
各登录状态下跳转场景大概可分为以下几种:
跳转非登录页
跳转登录页
跳转根路由
跳转未定义路由
解决方案:
- 跳转非登录页
在 router.beforeEach(前置守卫)中判断目标路由是否需要登录,需要登录则重定向到登录页,对于无需登录的如:404,注册,重置密码 等页面,直接进入 next() 即可,不做处理。
// 路由前置守卫
router.beforeEach((to, from, next) => {
const { meta, name } = to;
const { isLogin } = meta;
// token不存在时跳转非登录页,重定向到登录页
if (!getToken() && name !== 'Login' && isLogin) next({ path: '/login' });
// 其他场景
else next();
});
- 跳转登录页
在 router.beforeEach(前置守卫) 中判断,已登录时重定向到首页,未登录时理所应当到登录页,所以不做处理,直接进 next()
// 路由前置守卫
router.beforeEach(({ meta, name }, from, next) => {
const { title, isLogin } = meta;
if (title) document.title = title;
// token不存在时跳转非登录页,重定向到登录页
if (!getToken() && name !== 'Login' && isLogin) next({ path: '/login' });
// token存在时跳转登录页,重定向到首页
else if (getToken() && name === 'Login') next({ path: '/home' });
// 其他场景
else next();
});
- 跳转根路由
丢失路由路径的情况很常见,比如得到一个链接 http://localhost:8080/#/,如果未定义根路由渲染组件,那么此链接跳转后,会得到异常的空白页面,这要是上了生产,怕是要GG~,但如果你的 / 是像下面这样配置的,虽然不会出现访问根路由空白问题,但也需要兼容未登录时的登录页重定向。
const routes = [
{
path: '/',
name: 'Home',
meta: {
title: 'Homepage',
isLogin: true
},
component: () => import('@/views/Home')
}
];
你还可以通过设置别名的方式来规避根路由空白的问题:
https://next.router.vuejs.org/zh/guide/essentials/redirect-and-alias.html
正常情况下访问根路由,要么跳转登录页,要么跳转首页,所以,我们需要进行以下配置:
当你的根路由 / 未进行路由组件配置时,你需要定义访问 / 路径,重定向到 /home 或者 /login 路径,下列代码结合我们第一,第二点配置的路由前置守卫,可以分别适配两种跳转场景,未登录时访问 / 跳转到 /login,已登录时访问 / 跳转到 /home。
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'Home',
meta: {
title: 'Homepage',
isLogin: true
},
component: () => import('@/views/Home')
},
{
path: '/login',
name: 'Login',
meta: {
title: 'Login Page'
},
component: () => import('@/views/Home')
}
];
- 跳转未定义路由
网页链接在Copy N次的过程中,可能出现丢失路径,或者多加了一段路径的情况,比如 http://localhost:8080/#/mmp~ 然后被测试同学或者客户碰巧用上了,他们打开之后就会发现出现空白页面,还有你就会发现你的bug清单上多了一项,出现这种情况的原因很简单,你没有配置对应的路由渲染组件,所以为了规避这种异常状况,通常我们要配置一个 /404 的路由页面,然后使用通配符路由 * 来重定向到 /404/ 页面。
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/404',
name: 'NotFound',
meta: {
title: 'Page not found',
isLogin: false
},
component: () => import('@/views/NotFound')
},
// 所有未定义路由,全部重定向到404页
{
path: '*',
redirect: '/404'
}
];
所有未定义的路径都将匹配 * 这个路由定义,然后重定向到 /404,例如:
http://localhost:8080/#/jjyy => http://localhost:8080/#/404
http://localhost:8080/#/mmp => http://localhost:8080/#/404
据说 * 必须放在最后定义,不过我不放在最后好像也能跑?(??手动黑人问号??)
router / index.js 代码:
import Vue from 'vue';
import VueRouter from 'vue-router';
import { getToken } from '@/utils/cookies';
Vue.use(VueRouter);
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'Home',
meta: {
title: 'Home',
isLogin: true
},
component: () => import('@/views/Home')
},
{
path: '/login',
name: 'Login',
meta: {
title: 'Login'
},
component: () => import('@/views/Login')
},
{
path: '/404',
name: 'NotFound',
meta: {
title: 'Page not found',
isLogin: false
},
component: () => import('@/views/NotFound')
},
// 所有未定义路由,全部重定向到404页,必须放在最后
{
path: '*',
redirect: '/404'
}
];
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
/**
* 路由跳转后页面滚动到顶部
* 详见:https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html
*/
scrollBehavior: () => ({ y: 0 }),
routes
});
// 路由前置守卫
router.beforeEach(({ meta, name }, _, next) => {
const { title, isLogin } = meta;
if (title) document.title = title;
// token不存在时跳转非登录页,重定向到登录页
if (!getToken() && name !== 'Login' && isLogin) next({ path: '/login' });
// token存在时跳转登录页,重定向到首页
else if (getToken() && name === 'Login') next({ path: '/home' });
// 其他场景
else next();
});
export default router;