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 prop 或 router.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()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。

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

这样的写法,看起来好像没啥问题,但是忽略了请求资源是异步的,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()方向出口。

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

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

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

  1. 动态路由下刷新 页面空白

    前言 最近设计动态路由时,刷新页面空白.突然想起以前笔记里面记录过,翻看了下,今天得空儿分享出来. 问题描述 在全局前置守卫router.beforeEach里面加入动态路由设计时,刷新动态页面,明明 ...

  2. VUE动态路由下刷新丢失路由的解决方法

    目前在使用VUE3.X开发,发现加载动态路由的话,由于刷新页面就会重新加载VUEX,故会丢失已存在的state,但是又不想localStorage,sessionStorage. 经过多次试验,采取在 ...

  3. Vue-i18n在Routerd动态路由下实现国际化

    在Electron-vue-admin的项目中实现国际化的需求时,遇到一个问题,vue-i8n无法在router/index.js的路由菜单配置项内以下面常规的方法实现. //vue标签内使用(例:) ...

  4. Vue/React实现路由鉴权/导航守卫/路由拦截(react-router v6)

    欢迎来到我的博客

  5. Vue 动态路由的实现以及 Springsecurity 按钮级别的权限控制

    思路: 动态路由实现:在导航守卫中判断用户是否有用户信息,通过调用接口,拿到后台根据用户角色生成的菜单树,格式化菜单树结构信息并递归生成层级路由表并使用Vuex保存,通过 router.addRout ...

  6. 导航守卫又称为路由守卫

    路由进阶部分 – 导航守卫( 路由守卫 ) 作用: - 类似 [保安] 守卫路由 进 举例: 携带数据进 出 举例: 事情完成才能出 导航守卫一共有三种形式 全局导航守卫用的时候写在主文件中(main ...

  7. 【Vue】vue中的路由导航守卫(路由的生命周期)

    文章目录 全局前置守卫 可选的第三个参数 `next` 全局解析守卫 router.beforeResolve 全局后置钩子 路由独享的守卫 组件内的守卫 可用的配置 API 使用组合 API 完整的 ...

  8. Vue-5 路由参数的传递和获取(query 和 params),导航守卫和路由元信息,History模式

    Vue-5 路由传参的几种方式(query和params),获取路由参数,导航守卫和路由元信息,History模式 除了 props 和 $emit 之外,路由时也可以携带数据,即通过路由传参. 一. ...

  9. 55. VUE 导航守卫

    就是 如果你想跳转路由的时候干点什么 那么就用导航守卫,例如更换标题,当然你可以用生命周期函数,在我看来不切实际.  点击首页标题换首页 ,点击个人 标题换个人: 全局导航守卫 vue-router提 ...

  10. React进阶(五):导航守卫

    文章目录 一.前言 二.全局守卫 三.拓展阅读 一.前言 在<React进阶(四):路由介绍>博文中,介绍了React路由相关知识,在实际项目开发过程中,路由之间的跳转必定涉及权限.用户是 ...

最新文章

  1. 安卓系统底层C语言算法之测试参数是几个long型的算法
  2. linux——环境变量与文件查找
  3. js经典校验之注册与登录校验
  4. ug后处理如何加密_什么叫UG编程?UG编程是干嘛的?不得不看哦!的UG
  5. java根据ip查计算机名_Java如何从IP地址查找主机名?
  6. MySQL 开启远程登录权限
  7. VTK:Math之PerpendicularVector
  8. Message,MessageQueue,Looper,Handler详解+实例
  9. [整理]ASP.NET MVC 5
  10. python输出字体的大小_Toby的Python笔记 | 预备知识:安装openpyxl学做电子表格
  11. 移动开发:iphone开发之触摸事件详解
  12. 2020 CCPC网络赛 赛后感
  13. 英伟达 | 深度学习GPU最新情况
  14. python yield
  15. Windows Phone开发之路(6) XAML基础(下)
  16. springBoot笔记2
  17. 用Python将一个文件夹下多个子文件夹中相同文件拷贝到同一个文件夹中并重新命名
  18. java quartz配置
  19. 【正点原子STM32连载】第七章 认识HAL库 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  20. 可重用性,可维护性,可读性,可测试性,可用性,健壮性

热门文章

  1. TCP和HTTP的区别和联系
  2. kubeadm-deployment
  3. [JSOI2017]原力(分块+map(hash))
  4. Eclipse用法和技巧二十:一个快速打印技巧
  5. Bean被IoC容器销毁后还能使用吗?
  6. JVM监控及诊断工具命令行篇之jhat
  7. MyBatis源码阅读(五) ---Mapper接口的获取过程
  8. MyCat分片规则之取模分片
  9. Redis与Redisson的分布式锁
  10. String类的trim() 方法