背景
一个项目有很多个页面,有些页面是需要有权限的用户才能访问的.例如购物车结算页面,需要用户登录才能访问.
当我们发现一个没有登录的用户去访问需要权限的页面时,我们应该引导用户去登录页面,用户登录之后,页面将跳转到用户之前访问过的页面.
在项目中,用到了vue-router 提供的前置导航守卫,来控制有权限页面的跳转.
// 导入store,store中保存的是用户登录的token信息
import store from '@/store'
// 1.在router.js中,定义一个数组,保存需要权限的页面
const authLinks = ['/user', '/cart', 'userInfo']
// 2.添加前置导航守卫,控制有权限页面的跳转
// to 要去哪儿
// from 从哪儿来 to 和 from 是路由信息对象
// next 是放行函数
router.beforeEach((to, from, next) => {
// 判断访问的页面是否需要权限
if (authLinks.includes(to.path)) {
// 访问的页面需要权限,再判断用户是否登录,即是否有token,有token则放行
// token保存在store中,需要导入store
if (store.state.user.tokenInfo.token) {
// 存在token,说明用户是登录状态,放行
next()
} else {
// 不存在token,跳转到登录页面
next('/login')
}
} else {
// 访问的页面不需要权限,则放行
next()
}
})
上述方法出现了一个问题,即登陆后无法返回原页面.在实际场景中,用户在未登录状态下,进入购物车页面,应跳转到登录页面引导用户登录,用户登陆之后,跳转到之前访问过的页面,即购物车页面.
而上述方法用户登录后直接跳转到了首页,原因是在登录页面当用户点击了登录按钮,通过路由跳转编程式导航跳转到了首页
this.setTokenInfo(data.data)
// 路由跳转编程式导航
this.$router.push('/')
解决方法:修改next()
router.beforeEach((to, from, next) => {
// 判断访问的页面是否需要权限
if (authLinks.includes(to.path)) {
// 访问的页面需要权限,再判断用户是否登录,即是否有token,有token则放行
// token保存在store中
if (store.state.user.tokenInfo.token) {
// 存在token,说明用户是登录状态,放行
next()
} else {
// 不存在token,跳转到登录页面
//next() 底层实现和this.$router.push({})是一样的
next({
path: '/login',
query:{
backTo: to.fullPath // backTo字段名任意
// fullPath包含路由地址和参数,因为访问文章详情的url有可能会携带参数
// path只是路由地址
}
})
}
} else {
// 访问的页面不需要权限,则放行
next()
}
})
然后在登录页面,判断路由地址中是否包含backTo 字段
// 判断路由地址中是否包含backTo 字段 ,有这个字段, 应该让他去这个backTo对应的页面,没有就去首页
const backTo = this.$route.query.backTo
if (backTo) {
this.$router.push(backTo)
} else {
this.$router.push('/')
}
运行结果
当用户没有登录,进入user页面时,引导用户进行登录,此时路由地址中有backTo字段,点击登录按钮后,跳转到了user页面,而不是登录页面.