Skip to content

嵌套路由

嵌套路由是指:一个组件中包含另一个 <router-view>,从而形成层级结构的页面展示

/user/johnny/profile                   /user/johnny/posts 
┌──────────────────┐                  ┌──────────────────┐
│ User             │                  │ User             │
│ ┌──────────────┐ │                  │ ┌──────────────┐ │
│ │ Profile      │ │  ────────────>   │ │ Posts        │ │
│ │              │ │                  │ │              │ │
│ └──────────────┘ │                  │ └──────────────┘ │
└──────────────────┘                  └──────────────────┘

基本语法

  • 父组件中放置 <router-view>
vue
<!-- App.vue -->
<template>
  <router-view />
</template>

<!-- User.vue -->
<template>
  <div>
    <h2>User {{ $route.params.id }}</h2>
    <router-view />
  </div>
</template>
  • 路由配置中使用 children
ts
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      { path: 'profile', component: UserProfile },
      { path: 'posts', component: UserPosts },
    ],
  },
]
  • 当访问 /user/1/profile 时,渲染关系是:App.vue → User.vue → UserProfile.vue
  • 当访问 /user/1/posts 时,渲染关系是:App.vue → User.vue → UserPosts.vue

默认子路由

当你访问 /user/:id 时,如果希望仍然渲染一个子页面(比如用户主页),可以在 children 中添加空路径:

ts
{
  path: '/user/:id',
  component: User,
  children: [
    { path: '', component: UserHome }, // 默认子路由
    { path: 'profile', component: UserProfile },
  ],
}

嵌套的命名路由

如果使用命名路由(name),可以为子路由单独命名:

ts
{
  path: '/user/:id',
  component: User,
  children: [
    { path: '', name: 'user-home', component: UserHome },
    { path: 'posts', name: 'user-posts', component: UserPosts },
  ],
}

这将确保导航到 /user/:id 时始终显示嵌套路由。

ts
router.push({ name: 'user-posts', params: { id: 1 } })

警告

ts
router.push({ name: 'user-posts' })

[Vue Router warn]: Missing required param "id" for route "user-posts"

  • 不会跳转

  • 不会匹配到任何页面

  • 控制台会有警告 / 异常提示。

因为该路由的完整路径中存在一个 必填的动态参数 :id。在命名路由跳转时,Vue Router 必须依靠 params 填充这些占位符。 否则它无法正确构建最终的 URL。

在一些场景中,你可能希望导航到命名路由而不导航到嵌套路由。例如,你想导航 /user/:id 而不显示嵌套路由。那样的话,你还可以命名父路由,但请注意重新加载页面将始终显示嵌套的子路由,因为它被视为指向路径/users/:id 的导航,而不是命名路由:

ts
const routes = [
  {
    path: '/user/:id',
    name: 'user-parent',
    component: User,
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]

忽略父组件

当父路由只作为路径分组或管理逻辑,而不需要实际渲染组件时,可以省略父组件,顶层 <router-view> 会直接渲染子路由组件。

省略父路由的 componentcomponents

ts
const routes = [
  {
    path: '/admin', // 父路径
    children: [
      { path: '', component: AdminOverview },
      { path: 'users', component: AdminUserList },
      { path: 'users/:id', component: AdminUserDetails },
    ],
  },
]
  • 父路由 /admin 没有指定组件;

  • 所有子路由直接渲染在顶层 <router-view> 中;

  • 顶层 <router-view> 会跳过父组件,直接显示子组件。