动态路由下的导航守卫--(to,from,next)

1. 导航守卫–(to,from,next)

router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })
 
router.beforeEach((to, from, next) => {
  // ...
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中(没有执行next就一直等待)。

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    • next(‘/’) 或者 next({ path: ‘/’ }):跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: truename: 'home' 之类的选项以及任何用在 router-link 的 to proprouter.push 中的选项。
    • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

确保要调用 next 方法,否则钩子就不会被 resolved

router.beforeEach((to, from, next) => {
  if (to.matched.length ===0) {  //如果未匹配到路由
    from.path? next({ path:from.path}) : next('/');   //如果上级也未匹配到路由则跳转主页面,如果上级能匹配到则转上级路由
  } else {
    next();    //如果匹配到正确跳转
  }
});

2. 匹配所有路由–(按照书写的路由顺序匹配)

路由的匹配规则是按照书写的顺序执行的,第一条匹配成功则不去匹配下一条,利用这一特性,可以在所有匹配路由的下面拦截匹配所有路由:

//创建路由对象并配置路由规则
let router = new VueRouter({
    routes:[
       {path:'/',redirect:{name:"home"}},  // 重定向到主页
       {name:'home',path:'/home',component:Home},
       {name:'login',path:'/login',component:Login},
       {path:'*',component:NotFound},//全不匹配的情况下,匹配NotFound组件,路由按顺序从上到下,依次匹配。最后一个*能匹配全部,
    ]
});

3,next的理解–(不带参是放行,带参是重新跳转)

其实在路由守卫中,只有next()是放行,其他的诸如:next('/logon') 、 next(to) 或者 next({ ...to, replace: true })都不是放行,而是:中断当前导航,执行新的导航

比如说现在我有一个守卫,在守卫中我使用next('/logon'),肯定有同学认为是会直接跳转到/logon路由:

beforeEach((to, from, next) => {
  next('/logon')
}

然而实际上,它是中断这次导航,重新跳转到新的路由,于是又会触发新的路由守卫,也就是下图这样:

beforeEach((to, from, next) => {
  beforeEach(('/logon', from, next) => {
  	 beforeEach(('/logon', from, next) => {
  	 	 beforeEach(('/logon', from, next) => {
  	 	 	beforeEac...  // 一直循环下去...... , 因为我们没有使用 next() 放行
 		}
 	 }
  }
}

如果把这个守卫改一下,当我在地址栏输入/home时:

beforeEach((to, from, next) => {
   if(to.path === '/home') {
   	next('/logon')
   } else {
    // 如果要去的地方不是 /home , 就放行
   	next()
   }
}

这样一来,我第一次进入导航守卫是“/home”,但是被重新跳转到“/logon”,于是再次进入导航守卫,这回就走的else路径,next()放行,浏览器中变成/logon。

4,动态添加路由addRoutes()

动态添加路由addRoutes()是异步的,这会导致一个问题,当我们在addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()就立刻访问被添加的路由,然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。

例如我今天遇到的代码时这样的:

image-20211120112427346

这样的写法,看起来好像没啥问题,但是忽略了请求资源是异步的,addRoutes()也是异步的

先按照代码的设计者的逻辑过一遍(假设这两者都是同步的):

1,登录成功后,to.path是“/home”,这时候路由资源为空,发起请求获取到路由资源,使用addRoutes()添加路由,然后执行next()放行路由,于是浏览器变成/home,匹配上vue-router的路由,懒加载home/index.vue页面,然后发现有嵌套路由,需要重定向,于是变成“/home/homePage(假设是这个)”,再次进入导航守卫,因为已经有路由资源了,就直接next()放行,浏览器变成“/home/homePage",懒加载homePage的组件,于是渲染出页面。

然而,实际上呢,在第一次to.path是“/home”的时候,虽然发起获取路由资源的请求了,但它是异步的,还没执行完,更别提addRoutes()也是异步,更没执行完毕,于是就先执行底下的next()放行路由了!浏览器就变成/home了。

然而这时候,路由还没添加,肯定是匹配不到的对应路由的,于是白屏,需要等到路由资源请求回来了,并且添加到路由资源中了,才能匹配上路由(实际上这里又会进入一次守卫,可以简单理解为,浏览器在找不到路由时一直在轮询,直至查找到了再次进入导航守卫,执行next(),匹配路由,加载页面)

于是就可以知道,这个白屏的时间。其实取决于请求资源和添加路由的时间。

解决办法

此时就要使用next({ …to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。

next({ …to, replace: true })中的replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。

因此next({ …to, replace: true })可以写成next({ …to }),不过你应该不希望用户在addRoutes()还没有完成的时候,可以点击浏览器回退按钮搞事情吧。

其实next({ …to })的执行很简单,它会判断:

如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)直到其中的next({ …to})能找到对应的路由为止。

也就是说此时addRoutes()已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next) ,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),如果是,就执行next()放行。

如果守卫中没有正确的放行出口的话,会一直next({ …to})进入死循环 !!!

因此你还需要确保在当addRoutes()已经完成时,所执行到的这一次beforeEach((to, from, next)中有一个正确的next()方向出口。

于是我把代码更改成如下的样子:

image-20211120121245756

因为登陆后第一次”/home“时,next({…to,replace:true})第一次执行时,资源必然没有加载好,于是再进入beforeRouter(to,from,next),这时候,如果还没准备好路由资源,则再进一层beforeRouter(to,from,next)直到路由资源准备好了,于是走else中的next()。

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: vue路由守卫中的to、from和next分别表示什么意思? to:即将进入的路由对象,包含路由的路径、参数、查询、hash等信息。 from:当前导航正要离开的路由对象,也包含路由的路径、参数、查询、hash等信息。 next:必须调用该函数来resolve钩子,执行效果依赖next方法的调用参数。可以传入一个路由对象,或者false、true、或者一个Error实例。 ### 回答2: Vue.js 是一种轻量级的 JavaScript 框架,是一种用于将用户界面与数据相连接的 Web 应用程序的库。Vue.js 提供了一种名为Router(路由器)的机制,能够使得我们的应用程序根据 URL 的不同展现不同的内容。而 Vue.js 路由守卫(Guard)则是在路由到达之前/之后执行的函数钩子。 Vue 路由守卫涉及到三个参数:to、from、next。其中,to 表示即将到达的路由对象,from 表示当前导航正要离开的路由,而 next() 为守卫的控制权,调用该函数时意味着放行,否则就会导致路由无法继续执行。 在 Vue.js 路由导航被触发之前,可以执行以下几种类型的导航守卫: 1. 全局前置守卫 beforeEach(to, from, next) 全局前置守卫定义了全局前置守卫,会在导航到路由前执行。其参数为 to、from 和 next: to — 即将要进入的目标路由对象 from — 当前导航正要离开的路由 next() — 守卫的控制权,必须调用 next() 才能放行路由 2. 路由独享的守卫 beforeEnter(to, from, next) 路由独享守卫定义在单个路由的配置对象中。beforeEnter(to, from, next) 会在路由独享进入之前调用,其参数为 to、from 和 next: to — 即将要进入的目标路由对象 from — 当前导航正要离开的路由 next() — 守卫的控制权,必须调用 next() 才能放行路由 3. 组件内的守卫 beforeRouteEnter(to, from, next) 组件内的守卫 beforeRouteEnter(to, from, next) 会在路由进入组件文件之前被调用。由于此时该组件实例还没有被创建,因此在该守卫函数中访问不到 this。参数包括 to、from 和 next: to — 即将要进入的目标路由对象 from — 当前导航正要离开的路由 next() — 守卫的控制权,必须调用 next() 才能放行路由 4. 组件内的守卫 beforeRouteUpdate(to, from, next) 在同一路由内,不同组件的实例切换时,会触发组件的 beforeRouteUpdate 钩子函数。其参数包括 to、from 和 next: to — 即将要进入的目标路由对象 from — 当前导航正要离开的路由 next() — 守卫的控制权,必须调用 next() 才能放行路由 5. 组件内的守卫 beforeRouteLeave(to, from, next) 在离开当前路由时,组件内的守卫 beforeRouteLeave(to, from, next) 会被调用。它的参数包括 to、from 和 next: to — 即将要进入的目标路由对象 from — 当前导航正要离开的路由 next() — 守卫的控制权,必须调用 next() 才能放行路由 理解 Vue 路由守卫的作用和更深层次的含义,能够更加合理地控制应用程序的行为和业务逻辑,更好地保护用户的数据安全。 ### 回答3: vue路由守卫to from next是vue框架中用于控制页面访问权限的一种机制。在开发web应用过程中,经常需要进行身份验证、权限控制等安全相关的操作。为了实现这些功能,我们可以使用vue的路由系统,通过路由守卫来实现。 路由守卫由全局路由守卫、路由独享守卫和组件内的守卫组成。全局路由守卫会在进入或离开任何页面时触发,而路由独享守卫只在特定路由上触发。组件内的守卫则可以在组件内部实现身份验证和权限控制。 to参数代表目标路由,from参数代表来源路由,next参数是一个函数用于在路由守卫中控制路由的流程。to和from参数是路由对象,包含了当前导航正要离开的路由和即将前往的路由的信息。我们可以通过这些参数获取到当前的路由信息,并作出相应的处理。 next函数有两种用法:可以传入一个参数或不传参。如果不传参,则会继续导航到目标路由;否则,会中断导航并传递一个路由对象参数,导航到该路由。 在vue应用中,我们可以使用路由守卫来实现一些常见的操作,例如: 1. 身份验证:通过在路由独享守卫或组件内的守卫中验证用户是否已登录,以确定是否能够访问该页面。 2. 权限控制:在路由独享守卫或组件内的守卫中根据用户角色等信息,判断是否具有访问该页面的权限。 3. 页面重定向:在全局路由守卫中,可以根据用户角色和当前页面,自动跳转到相应的页面。 总之,vue的路由守卫可以方便地控制应用的访问权限和流程,是构建高效稳定的web应用的必备工具。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值