重定向与别名

在应用开发中,有时需要将一个路径指向另一个路径——可能是因为页面迁移、URL 规范调整,或者需要为同一页面提供多个入口。vitarx-router 提供了重定向别名两种机制来满足这些需求。

重定向

重定向是指当用户访问某个路径时,自动跳转到另一个路径。通过 redirect 字段配置。

字符串重定向

最简单的形式,直接指定目标路径:

ts
const routes = defineRoutes({ path: '/old-path', redirect: '/new-path' })

访问 /old-path 时,会自动跳转到 /new-path

名称重定向

使用路由名称作为重定向目标:

ts
const routes = defineRoutes(
  { path: '/home', redirect: 'dashboard' },
  { path: '/dashboard', name: 'dashboard', component: Dashboard }
)

INFO

名称重定向的目标不以 / 开头,因此会被识别为路由名称而非路径。

对象重定向

使用对象形式可以同时传递查询参数:

ts
const routes = defineRoutes({
  path: '/old-user',
  redirect: { index: '/user', query: { from: 'old' } }
})

访问 /old-user 时,会跳转到 /user?from=old

函数重定向

使用函数可以根据条件动态决定重定向目标:

ts
const routes = defineRoutes({
  path: '/search',
  redirect: to => {
    // 根据目标路径的查询参数决定跳转
    return '/search/results'
  }
})

函数接收 to 参数(类型为 RouteLocation),表示即将进入的路由位置,返回值可以是字符串、路由名称或 NavTarget 对象。

WARNING

vitarx-router 最多允许 16 次连续重定向,超过此限制会抛出错误以防止无限循环。这通常意味着路由配置中存在循环重定向,请检查你的路由定义。

ts
// ❌ 危险:循环重定向
{ path: '/a', redirect: '/b' },
{ path: '/b', redirect: '/a' }

别名

别名允许一个路由拥有多个访问路径,与重定向不同,别名不会改变浏览器的 URL——用户访问别名路径时,URL 保持不变,但渲染的是同一路由的组件。

单个别名

使用 alias 字段指定单个别名:

ts
const routes = defineRoutes({ path: '/home', alias: '/index', component: Home })

访问 /home/index 都会渲染 Home 组件,且 URL 不会发生变化。

多个别名

alias 也接受数组形式,为路由指定多个别名:

ts
const routes = defineRoutes({ path: '/home', alias: ['/index', '/start'], component: Home })

访问 /home/index/start 都会渲染 Home 组件。

空字符串别名

在子路由中,空字符串 '' 作为别名时,表示将父路径映射到当前子路由:

ts
const routes = defineRoutes({
  path: '/admin',
  component: AdminLayout,
  children: [
    {
      path: 'dashboard',
      alias: '', // /admin 也会匹配此路由
      component: AdminDashboard
    }
  ]
})

访问 /admin/admin/dashboard 都会渲染 AdminDashboard 组件。

WARNING

动态路由的别名必须与主路径具有相同的参数名称和可选性。以下写法是无效的:

ts
// ❌ 错误:别名的参数与主路径不一致
{ path: '/user/{id}', alias: '/people/{userId}', component: UserProfile }
// 别名使用了不同的参数名 userId

// ✅ 正确:别名使用相同的参数名和可选性
{ path: '/user/{id}', alias: '/people/{id}', component: UserProfile }

完整示例

tsx
import { createRouter, defineRoutes, RouterView, RouterLink } from 'vitarx-router'
import { createApp } from 'vitarx'

function Home() {
  return <h2>首页</h2>
}

function Dashboard() {
  return <h2>仪表盘</h2>
}

function AdminLayout() {
  return (
    <div>
      <nav>
        <RouterLink to="/admin">仪表盘</RouterLink>
        <RouterLink to="/admin/users">用户</RouterLink>
      </nav>
      <RouterView />
    </div>
  )
}

function AdminDashboard() {
  return <h2>管理后台</h2>
}

function AdminUsers() {
  return <h2>用户管理</h2>
}

const routes = defineRoutes(
  // 别名:/index 和 /start 都指向首页
  { path: '/home', alias: ['/index', '/start'], component: Home },
  // 重定向:/old-dashboard 跳转到 /dashboard
  { path: '/old-dashboard', redirect: '/dashboard' },
  { path: '/dashboard', name: 'dashboard', component: Dashboard },
  {
    path: '/admin',
    component: AdminLayout,
    children: [
      // 空字符串别名:/admin 也匹配此路由
      { path: 'dashboard', alias: '', component: AdminDashboard },
      { path: 'users', component: AdminUsers }
    ]
  }
)

const router = createRouter({ routes })

function App() {
  return <RouterView />
}

createApp(App).use(router).mount('#app')