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
模板