Vue 路由导航控制与守卫详解

导航守卫是 Vue Router 中控制路由跳转的核心机制,它允许开发者在路由切换的不同阶段插入自定义逻辑。本文将深入解析各类导航守卫及其应用场景。

一、导航守卫分类

1. 全局守卫

全局守卫作用于所有路由跳转:

const router = createRouter({ ... })

// 前置守卫
router.beforeEach((to, from, next) => {
  // 在路由跳转前执行
  console.log(`Navigating from ${from.path} to ${to.path}`)
  next() // 必须调用 next() 继续导航
})

// 后置守卫
router.afterEach((to, from) => {
  // 在路由跳转后执行,没有 next 参数
  logPageView(to.fullPath)
})

实践建议

  • 全局前置守卫适合做权限控制、登录验证等全局性逻辑
  • 后置守卫适合做页面统计、埋点等不需要阻塞导航的操作

2. 路由独享守卫

在路由配置中直接定义的守卫:

const routes = [
  {
    path: '/admin',
    component: AdminPanel,
    beforeEnter: (to, from, next) => {
      if (!isAdmin()) {
        next('/login') // 重定向
      } else {
        next()
      }
    }
  }
]

实践建议

  • 适合特定路由的权限校验
  • 比全局守卫更早执行

3. 组件内守卫

在组件内部定义的守卫:

const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this`
    next(vm => {
      // 通过 `vm` 访问组件实例
    })
  },
  beforeRouteUpdate(to, from, next) {
    // 当前路由改变但组件被复用时调用
    // 可以访问 `this`
    this.userData = fetchUser(to.params.id)
    next()
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    if (this.hasUnsavedChanges) {
      if (confirm('有未保存的更改,确定离开?')) {
        next()
      } else {
        next(false)
      }
    } else {
      next()
    }
  }
}

执行顺序

图1

二、导航行为控制

1. 取消导航

next(false) // 中断当前导航

2. 重定向

next('/login') // 重定向到登录页
next({ path: '/login', query: { redirect: to.fullPath } }) // 带参数重定向

3. 错误处理

next(new Error('Network Error')) // 触发路由错误回调

router.onError(error => {
  console.error('路由错误:', error)
  showErrorPage()
})

实践建议

  • 在全局守卫中统一处理未捕获的导航错误
  • 对于权限类错误,可以提供友好的重定向而不是直接报错

三、常见应用场景

1. 登录验证

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next({
      path: '/login',
      query: { redirect: to.fullPath }
    })
  } else {
    next()
  }
})

2. 页面标题管理

router.afterEach((to) => {
  document.title = to.meta.title || '默认标题'
})

3. 滚动行为控制

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else if (to.hash) {
      return { el: to.hash }
    } else {
      return { top: 0 }
    }
  }
})

四、性能与调试建议

  1. 避免过度使用全局守卫:全局守卫会在每次导航时执行,复杂逻辑可能影响性能
  2. 守卫中的异步操作

    beforeRouteEnter(to, from, next) {
      fetchData().then(data => {
     next(vm => vm.setData(data))
      })
    }
  3. 调试技巧

    router.beforeEach((to, from, next) => {
      console.log('[路由跳转]', from.path, '->', to.path)
      next()
    })

导航守卫是 Vue Router 强大功能的体现,合理使用可以构建出既安全又用户体验良好的应用。根据具体场景选择合适的守卫类型,并注意保持守卫逻辑的简洁和高效。

评论已关闭