36.导航守卫理解
路由守卫:分为全局守卫、独享守卫、组件内守卫。
- 分为全局守卫(常用):一旦配置,那么作用范围就是所有的路由,只要路由发生改变就会触发,全局路由又分为全局前置守卫和全局后置守卫。
- 独享守卫(常用):是在进入组件时被调用,区别就在于,想对哪个路由进行权限控制就直接在其路由配置项中添加守卫,作用域也仅限于该路由。举例:假设用户刚登录成功,能直接跳转支付成功页面或者订单页面吗?答案是不能。
- 组件内守卫(不常用):当使用路由规则进入该组件或离开该组件时,就会触发组件内守卫的调用,而组件内守卫一般写在组件内部,它的作用于范围也仅限于该组件。举例:进某个屋子之前怎么怎么地,离开后又怎么怎么地,有点类似于后端的切面,进入方法前怎么怎么地,离开方法后怎么怎么地。
重难点说明
- 理解导航守卫
2) 使用导航守卫实现以下功能
a. 只有登陆了, 才能查看交易/支付/个人中心界面
b. 只有没有登陆, 才能查看登陆界面
c. 只有携带的skuNum以及sessionStorage中有skuInfo数据, 才能查看添加购物车成功的界面
d. 只能从购物车界面, 才能跳转到交易界面
e. 只能从交易界面, 才能跳转到支付界面
f. 只有从支付界面, 才能跳转到支付成功的界面
导航守卫是什么?
1). 导航守卫是vue-router提供的下面2个方面的功能
a. 监视路由跳转 -->回调函数
b. 控制路由跳转
2). 应用
a. 在跳转到界面前, 进行用户权限检查限制(如是否已登陆)
b. 在界面离开前, 做收尾工作
导航守卫分类
1). 全局守卫: 针对任意路由跳转
a. 全局前置守卫
b. 全局后置守卫
2). 路由独享的守卫
前置守卫
3). 组件守卫: 只针对当前组件的路由跳转
a. 进入
b. 更新
c. 离开
相关API
1). 全局前置守卫: 在准备跳转到某个路由组件之前 (在开发中用的比较多)
router.beforeEach((to, from, next) => {// before enter each route component
...
})
说明:
①. to: 目标route
②. from: 起始route
③. next: 函数
next(): 执行下一个守卫回调, 如果没有跳转到目标路由
next(false)/不执行: 跳转流程在当前处中断, 不会跳转到目标路由组件
next(path): 跳转到指定的另一个路由
2). 全局后置守卫: 在跳转到某个路由组件之后
router.afterEach((to, from) => {
})
3). 路由独享守卫
beforeEnter: (to, from, next) => {
}
3). 组件守卫
// 在当前组件对象被创建前调用, 不能直接访问this(不是组件对象)
// 但可以通过next(component => {}), 在回调函数中访问组件对象
beforeRouteEnter (to, from, next) {
next(component => {})
},
// 当前组件对象将要更新前调用, 可以访问this
beforeRouteUpdate (to, from, next) {
},
// 在当前组件离开前调用, 可以访问this
beforeRouteLeave (to, from, next) {
next()
}
修改代码:
src/pages/Home/index.vue Home组件中删除触发action
删除this.$store.dispatch('reqUserInfo');
src/router/index.js
let router = new VueRouter({
...
})
//全局守卫:前置守卫(在路由跳转之间进行判断)
router.beforeEach(async (to, from, next) => {
//to:获取到要跳转到的路由信息
//from:获取到从哪个路由跳转过来来的信息
//next: next() 放行 next(path) 放行
//获取仓库中的token-----可以确定用户是登录了
let token = store.state.user.token;
let name = store.state.user.userInfo.name;
//用户登录了
if(token){
//已经登录而且还想去登录------不行
if(to.path=="/login"||to.path=='/register'){
next('/');
}else{
//已经登陆了,访问的是非登录与注册
//登录了且拥有用户信息放行
if(name){
next();
}else{
//登陆了且没有用户信息
//在路由跳转之前获取用户信息且放行
try {
await store.dispatch('reqUserInfo');
next();
} catch (error) {
//token失效从新登录
await store.dispatch('reqLogout');
next('/login')
}
}
}
}else{
//未登录:不能去交易相关、不能去支付相关【pay|paysuccess】、不能去个人中心
//未登录去上面这些路由-----登录
let toPath = to.path;
if(toPath.indexOf('/trade')!=-1 || toPath.indexOf('/pay')!=-1||toPath.indexOf('/center')!=-1){
//把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】
next('/login?redirect='+toPath);
}else{
//去的不是上面这些路由(home|search|shopCart)---放行
next();
}
}
});
export default router;
src/pages/Login/index.vue
methods: {
//登录的回调函数
async reqUserLogin() {
try {
//成功
const {
phone, password} = this;
phone && password && await this.$store.dispatch('reqUserLogin',{
phone, password});
//判断query是否有参数,有就登录后重定向
let goPath = this.$route.query.redirect||'/home';
//跳转到首页
this.$router.push(goPath);
} catch (error) {
//失败
alert(error.message)
}
}
}
注意点1:
问题:全局组件中to, from, next都代表啥?
答案:
- to:获取到要跳转到的路由信息
- from:获取到从哪个路由跳转过来来的信息
- next: next() 放行 next(path) 放行
注意点2:跳转路由的逻辑很复杂,具体梳理如下:
判断是否用户登录?
已登录:判断跳转路由是否想去('/login')或者('/register')?
是:禁止跳转,并跳转到首页('/')
不是:判断是否拥有用户信息?
- 有:派发getUserInfo并放行
- 没有:派发userLogout并路由跳转到登录页('/login')
未登录:判断跳转路由是否想去交易相关('/trade')、支付相关('/pay')、个人中心相关('/center')
- 是:禁止跳转,并路由跳转到登录页('/login')
- 不是:放行
注意点3:
问题:如何设置路由守卫呢?
答案:在src/router/index.js中就可以配置,只不过由原来的默认导出路由改为先定义router变量接收,然后中间配置路由守卫,最后导出路由。
注意点4:
问题:为啥else里面的登录后面会有个重定向?干啥用的?
答案:会有这种场景需求:之前是登录后默认都是跳转的/home首页,现在有个需求:用户未登录情况下点击跳转订单页 -> 先跳转到登录页 -> 当登陆成功后应该跳转到订单页而不是首页,所以这块补充了redirect并配合登录方法重定向到想去的位置。
本人其他相关文章链接
1.vue尚品汇商城项目-day05【30.登录与注册静态组件(处理公共图片资源问题)+31.注册的业务+登录业务】
2.vue尚品汇商城项目-day05【33.token令牌理解+34.用户登录携带token获取用户信息+35.退出登录】
3.vue尚品汇商城项目-day05【36.导航守卫理解】