前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue Router 导航守卫:避免多次执行的陷阱与解决方案

Vue Router 导航守卫:避免多次执行的陷阱与解决方案

原创
作者头像
yaogengzhu
发布2023-12-12 17:10:39
1.7K0
发布2023-12-12 17:10:39
举报
文章被收录于专栏:前端轻松一刻

导语: Vue Router 是 Vue.js 官方提供的路由器,它用于处理单页应用(SPA)中的路由导航。在 Vue Router 中,导航守卫是非常重要的功能,它可以在路由跳转之前或之后执行一些特定的操作。但是,如果你不小心,导航守卫可能会多次执行,这可能会导致一些问题。本文将介绍如何避免导航守卫多次执行,并提供解决方案。

导航守卫的基本概念

在 Vue Router 中,导航守卫分为四个阶段:beforeEach、beforeEnter、afterEach 和 afterEnter。它们分别在导航开始、进入路由组件、导航完成和路由组件加载完成后执行。

  • beforeEach:在每条路由的进入之前执行,且仅对当前路由有效。
  • beforeEnter:在进入路由组件之前执行,且仅对当前路由有效。
  • afterEach:在每条路由的完成之后执行,且仅对当前路由有效。
  • afterEnter:在路由组件加载完成之后执行,且仅对当前路由有效。

避免多次执行的陷阱

有时,我们需要在路由守卫中执行一些操作,例如检查用户是否已登录。如果我们在每个路由的 beforeEach 守卫中执行这个操作,就可能会出现问题。因为每次导航时,都会执行 beforeEach 守卫,即使路由没有改变,也会重新执行。这就导致了操作被多次执行,可能会导致一些问题。

举个例子,假设我们在 beforeEach 守卫中检查用户是否登录,如果未登录,则跳转到登录页面。如果用户在登录页面已经登录,但未完成登录操作就关闭了页面,再次打开页面时,由于 beforeEach 守卫会多次执行,会导致用户再次被重定向到登录页面,这就不是我们想要的结果。

实际项目中的陷阱

举例:

代码语言:javascript
复制
...省略代码

router.afterEach((to, from) => {
  if (to.path !== from.path) {
// 这里发送了某次接口请求
    axios.get('xxxx')
  }
});

...省略代码

onMounted(() => {
//
})

如果我们切换组件,再次初始化这个组件,会导致这个axios.get('xxxx') 这个方法被调用多次。

原因: 在 Vue Router 中,当你使用 router.afterEach 添加一个全局导航守卫时,这个导航守卫会被存储在 Vue Router 的内部实例中。当路由发生变化时,Vue Router 会从内部实例中获取这些导航守卫,并在适当的时机执行它们。

具体来说,当你在组件中使用 router.afterEach 时,这个导航守卫会被添加到 Vue Router 的全局配置中,而不是存储在组件的调用栈中。因此,即使组件被销毁,这个导航守卫仍然会保留在 Vue Router 的内部实例中,并在下一次路由变化时继续执行。

总之,全局导航守卫不会存储在组件的调用栈中,而是存储在 Vue Router 的内部实例中。这就是为什么在组件被销毁后,导航守卫仍然会继续执行的原因。

提供解决方案(举例)

为了避免导航守卫多次执行,我们可以采用以下两种方法:

重点: 在全局使用统一的拦截,不要在组件中使用,避免导致在组件中使用,组件被销毁,实际上拦截器上的函数是不会被销毁的,当你再次初始化时,这时会导致意外的执行两次、多次

1. 使用 router.afterEach(() => { ... })

在 afterEach 守卫中执行操作可以避免多次执行的问题。因为 afterEach 守卫只在导航完成之后执行,无论路由是否改变。

例如,我们可以将用户登录检查操作放在 afterEach 守卫中:

代码语言:javascript
复制
router.afterEach(() => {
  if (!loginStatus) {
    router.replace('/login')
  }
})

在这个例子中,afterEach 守卫在每条路由完成之后执行,如果用户未登录,则使用 router.replace() 方法将用户重定向到登录页面。这样,无论用户如何导航,只要他们未登录,他们就会被重定向到登录页面,避免了导航守卫多次执行的问题。

2. 使用 router.beforeRouteLeave(to, from, next)

另一个避免导航守卫多次执行的方法是使用 beforeRouteLeave 守卫。它只对即将离开的路由有效,因此可以避免在进入路由组件之前多次执行操作。

例如,我们可以在 beforeRouteLeave 守卫中检查用户是否登录:

代码语言:javascript
复制
router.beforeRouteLeave((to, from, next) => {
  if (!loginStatus) {
    next('/login')
  } else {
    next()
  }
})

在这个例子中,beforeRouteLeave 守卫在即将离开当前路由之前执行,如果用户未登录,则使用 next('/login') 方法将用户重定向到登录页面。这样,无论用户如何导航,只要他们未登录,他们就会被重定向到登录页面,避免了导航守卫多次执行的问题。

总结

在 Vue Router 中,导航守卫是非常有用的功能,但它可能会导致多次执行的问题。为了避免这个问题,我们可以使用 router.afterEach(() => { ... })router.beforeRouteLeave((to, from, next) => { ... }) 方法来避免多次执行。根据你的具体情况选择合适的方法,使你的应用更加稳定和可靠。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导航守卫的基本概念
  • 避免多次执行的陷阱
  • 提供解决方案(举例)
    • 1. 使用 router.afterEach(() => { ... })
      • 2. 使用 router.beforeRouteLeave(to, from, next)
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档