1. 前言
1.路由确实在
vue
大型项目中听常用的,挺重要的,但是一般的小项目其实不用也没事
2.大家觉得难的 可能重点是路由守卫
3.那就试试自己能不能讲明白吧
4.当然还是建议大家看看 官网的路由守卫
2. 先从路由监听说起吧
2.1 首先路由系列的文章vue路由-2编程式导航存在通过路由切换的时候,
created
直走一次的问题,
2.2 解决方案 监听 -1
参数的名字 一般都叫
to
from
或者newV, oldV
to: Route
: 即将要进入的目标 路由对象
from: Route
: 当前导航正要离开的路由
watch:{
$route(to,from){
console.log(from.path);//从哪来
console.log(to.path);//到哪去
//界面变化了就发请求
}
},
这种写法也有个问题,第一次的时候不走
2.3 解决方案 监听-2
immediate:true
设置 立刻监听,第一次切换也会走的
watch:{
$route:{
immediate:true,
handler(newValue,oldValue){
console.log("详情页---newV:",newValue);
console.log("详情页---oldV:",oldValue);
}
},
},
3.导航守卫
3.1 官方定义
正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
3.2 场景
路由守卫嘛 就是保护路由的 ,怎么保护呢
主要就是在进入路由之前进行拦截
一般都是 某些界面必须登录才能访问的时候做个守卫,比如
最近某些购物类网站,点击购物车相关操作话,如果你没有登录的话,会直接跳转到登录界面;
在以前是会正常跳到购物车界面,付账的时候在登录,登录后购物车信息是都在的
5. 全局守卫配置
5.1 标记需要进行守卫的路由
一般通过路由配置
meta
属性
路由文件
{
path: '/address',
name: 'Address',
component: () => import('../views/address.vue'),
meta:{
title: "标题",
icon: "图标",
needLogin:true
}
},
1.
meta
哈哈没想到这个时候正式元宇宙大火的概念
2.扯回整体, 这里的meta
是一些原配置信息
3.needLogin
用来标记某个页面路由是否需要登录才能访问
4.title
实际开发中,如果配置菜单 也可以配置标题
5.icon
实际开发中,如果配置菜单 也可以配置菜单图标
5.2守卫逻辑
- 判断哪个路由需要守卫
if(to.meta.needLogin)
- 不需要守卫的 直接 走
else next()
- 需要守卫的进行第二步判断, 当前是否登录
登录的时候发请求 请求成功 存放 一个auth
或者token
到本地localStorage
- 如果现在已经登录 直接
next()
放行
5.如果没登录 嘿嘿此路是我开,此树是我栽,要想过,得听话,
回去登录去
注意的是 这里跳转到登录界面,需要把拦截路由的地址传过去,
为啥传???
那还不是为了用户体验,为了顾客,为了逻辑闭环
比如用户从点击购物车界面 跳转到了登录界面,用户登录后,肯定要给界面重置到 购物车界面嘛,
5.3 具体守卫代码 方式-1
// 全局守卫
router.beforeEach((to,from,next)=>{
// 判断路由是否需要守卫
//meta数据的方式
if(to.meta.needLogin){
// 是否登录
if(localStorage.token){
next()
}else{
next("/login?redirect="+to.fullPath)
}
}else{
//不需要守卫,直接放行
next()
}
})
export default router
5.4具体守卫代码 方式-2
router.beforeEach((to, from) => {
if (to.meta.needLogin) {//说明当前路由需要登录之后才可进入
if (!localStorage.token) {//还没登录 不为空 就行 简单的判断
// return "/login?redirect=" + to.name;
return "/login?redirect=" + to.fullPath;
}
}
})
这个不用
next
,但如果参数写了next
就必须用,不然不放行嘛,界面就一个也出不来
to.name
的方式 传的是 命名路由 跳转的时候也需要使用命名路由跳转
this.$router.push({ name: this.$route.query.redirect});
to.fullPath
的方式 传的是path
路径
用push
也行,但是也可用replace
this.$router.replace(this.$route.query.to);
6. 登录后跳回去的配置
loginBtn() {
this.isdisabled = true;
setTimeout(() => {
alert("登录成功");
this.isdisabled = false;
localStorage.token = "yzs假冒token";
// 登录成功之后 回到被拦截的页面
this.$router.replace(this.$route.query.redirect);
}
}, 3000);
},
守卫的时候传参方式
1.可以传 通过
query
传递 path路径
2.也可以通过params
传参
3.注意登录成功后 获取值的方式就行
query:{redirect:"/two"} ,
params: { toRouterName: to.name }})
命名路由的写法
this.$router.push({ name: this.$route.params.toRouterName });
这样就形成了逻辑闭环 ,当然你还需退出或者注销的时候修改状态
7.单个路由守卫
全局守卫,肯定是每个路由跳转都要进行判断的,也就是
each
遍历,这里面的效率问题就需要考虑
所以,如果只是极个别的路由需要判断,那就单独守卫
比如保护整村的人,和保护一个人那是完全不一样的
注意和全局的不同
- 钩子不一样了,这个是
Enter
进到这个路由了,判断
2.因为已经进到这个路由了,自然也不需要在判断哪个路由需要守卫了- 直接判断登录状态就行
{
path: '/cart',
name: 'Cart',
component: () => import("@/views/cart.vue"),
meta: {
title: "标题",
icon: "图标",
needLogin: true
},
//************* */ 单个的路由守卫
beforeEnter(to, from, next) {
// 判断当前是否登录
if (localStorage.token) {
next()
} else {
next({ name: "Three",
query:{to:"/cart"} ,
params: { toRouterName: to.name },})
}
}
},
8. 组件级守卫
1.和
methds
是同级的
2.beforeRouteEnter
和 单独的守卫beforeEnter
写法是不一样的
3.这个是存储localStorage
的逻辑
4.login
页和单个守卫用的是一样的
beforeRouteEnter(to, from, next) {
// 当前是否登录
if (localStorage.token) {
next();
} else {
next({ name: "Login", params: { toRouterName: to.name } });
}
},
9. 组件级守卫 钩子详解
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
1. 注意 Enter
钩子不能访问 this
因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意
beforeRouteEnter
是支持给next
传递回调的唯一守卫。对于beforeRouteUpdate
和beforeRouteLeave
来说,this
已经可用了,所以不支持传递回调,因为没有必要了。
10.完整的导航解析流程
1.导航被触发。
2.在失活的组件里调用beforeRouteLeave
守卫。
3.调用全局的beforeEach
守卫。
4.在重用的组件里调用beforeRouteUpdate
守卫 (2.2+)。
5.在路由配置里调用beforeEnter
。
6.解析异步路由组件。
7.在被激活的组件里调用beforeRouteEnter
。
8.调用全局的beforeResolve
守卫 (2.5+)。
9.导航被确认。
10.调用全局的afterEach
钩子。
11.触发DOM
更新。
12.调用beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
11. 想学习更多的实战配置 可以去看下各大开源的项目源码
比如各大框架的
admin
模板
参考资料
路由守卫