路由独享守卫

路由独享守卫是定义在路由配置上的守卫,只在进入该路由时触发。相比全局守卫,它更加精确,适合针对特定路由的拦截逻辑。

beforeEnter

beforeEnter 守卫直接定义在路由配置对象中,只在导航到该路由时触发。

单个守卫函数

最简单的用法是传入一个守卫函数:

ts
const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from) => {
      if (!isAdmin()) {
        return '/dashboard'
      }
    }
  }
]

守卫函数的返回值规则与全局前置守卫一致,详见 全局守卫 - 守卫返回值

守卫数组

beforeEnter 也支持传入一个守卫函数数组,它们会按顺序依次执行:

ts
const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: [requireAuth, requireAdmin]
  }
]

function requireAuth(to, from) {
  if (!isLoggedIn()) {
    return '/login'
  }
}

function requireAdmin(to, from) {
  if (!isAdmin()) {
    return '/dashboard'
  }
}

INFO

beforeEnter 为数组时,守卫按数组顺序依次执行。如果某个守卫返回 false 或重定向,后续守卫将不再执行。

执行顺序

当路由存在嵌套关系时,beforeEnter 的执行遵循 父路由优先 的原则:

  1. 全局 beforeEach 守卫
  2. 父路由的 beforeEnter
  3. 子路由的 beforeEnter
ts
const routes = [
  {
    path: '/admin',
    component: AdminLayout,
    beforeEnter: (to, from) => {
      console.log('1. 父路由 beforeEnter')
    },
    children: [
      {
        path: 'dashboard',
        component: AdminDashboard,
        beforeEnter: (to, from) => {
          console.log('2. 子路由 beforeEnter')
        }
      }
    ]
  }
]

与全局守卫的区别

特性全局守卫路由独享守卫
作用范围所有导航仅进入特定路由时
定义位置router.beforeEach() 或 createRouter 选项路由配置的 beforeEnter 字段
执行时机每次导航仅匹配到该路由时
适用场景通用逻辑(如登录验证)特定路由逻辑(如权限检查)

WARNING

beforeEnter 只在进入路由时触发。如果路由参数发生变化但组件不变(例如从 /user/1 导航到 /user/2),beforeEnter 不会再次触发。如需处理这种情况,请使用组件内的 onBeforeRouteUpdate

完整示例

ts
import { createRouter } from 'vitarx-router'

const routes = [
  {
    path: '/',
    component: Home
  },
  {
    path: '/user/{id}',
    component: User,
    beforeEnter: async (to, from) => {
      // 验证用户是否存在
      const userId = to.params.id
      const exists = await checkUserExists(userId)
      if (!exists) {
        return '/404'
      }
    }
  },
  {
    path: '/admin',
    component: AdminLayout,
    beforeEnter: [requireAuth, requireAdmin],
    children: [
      {
        path: 'dashboard',
        component: AdminDashboard
      },
      {
        path: 'settings',
        component: AdminSettings,
        beforeEnter: (to, from) => {
          // 额外的设置页面权限检查
          if (!canEditSettings()) {
            return '/admin/dashboard'
          }
        }
      }
    ]
  }
]

const router = createRouter({
  mode: 'hash',
  routes
})

组件内守卫 — 了解如何在组件内部注册路由守卫。