嵌套路由:children配置、命名视图、多级路由实战场景

嵌套路由,说白了就是路由里面套路由。我刚开始用 Vue Router 的时候,总觉得这玩意儿不就是多写几层路径吗?后来在做一个后台管理系统时,才真正体会到它的威力。

你想想看,一个典型的后台页面,左边是菜单,右边是内容区。点击不同的菜单项,右边的内容区要切换不同的组件。这种场景,用嵌套路由来处理,简直不要太舒服。

children 配置:路由的父子关系

先看一个最简单的例子。假设我们有一个用户管理模块,路径是 /users,下面有用户列表和用户详情两个子页面。

const routes = [
  {
    path: '/users',
    component: UserLayout,
    children: [
      {
        path: '',
        component: UserList
      },
      {
        path: ':id',
        component: UserDetail
      }
    ]
  }
]

这里有个细节要注意:children 里的 path 不要加 / 前缀。加了的话,它会变成绝对路径,就不是嵌套关系了。嗯,这个坑我踩过。

父组件里必须放一个 <router-view>,子路由的内容才会渲染出来。就像这样:

<template>
  <div class="user-layout">
    <h2>用户管理</h2>
    <router-view></router-view>
  </div>
</template>

我个人习惯把父组件叫做 Layout 组件,它只负责布局,不负责具体业务逻辑。这样代码结构更清晰。

多级嵌套:三层甚至更深

嵌套路由可以不止一层。我在项目中遇到过需要四层嵌套的场景——一个电商后台,从「商品管理」到「商品分类」再到「分类编辑」,最后还要弹出一个「属性配置」的对话框。

来看一个三层嵌套的例子:

const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout,
    children: [
      {
        path: 'orders',
        component: OrdersLayout,
        children: [
          {
            path: '',
            component: OrderList
          },
          {
            path: ':orderId',
            component: OrderDetail
          }
        ]
      }
    ]
  }
]

每一层都要有一个 <router-view>。说白了,就是每一级路由都对应一个容器组件,子路由的内容在容器的 <router-view> 里渲染。

注意:嵌套层级太深会让路由配置变得难以维护。我个人建议,超过三层就要考虑是否真的需要这么深。有时候用命名视图或者组件组合的方式,反而更清晰。

命名视图:一个页面多个出口

有时候一个页面需要多个 <router-view>,比如一个页面同时展示侧边栏、主内容区和底部信息。这时候命名视图就派上用场了。

<template>
  <div class="layout">
    <router-view name="sidebar"></router-view>
    <router-view name="main"></router-view>
    <router-view name="footer"></router-view>
  </div>
</template>

路由配置里,用 components(注意是复数)来指定每个命名视图对应的组件:

const routes = [
  {
    path: '/profile',
    components: {
      sidebar: SidebarComponent,
      main: ProfileComponent,
      footer: FooterComponent
    }
  }
]

默认的 <router-view> 没有 name 属性,它的名字就是 default。所以如果你只有一个视图,用 component 就行。如果有多个,必须用 components

小技巧:命名视图和嵌套路由可以组合使用。比如父路由有一个默认视图,子路由里可以定义多个命名视图。我曾经在一个复杂的报表页面里,用这种方式同时展示了图表、表格和筛选条件三个区域,每个区域独立路由,互不干扰。

实战场景:后台管理系统

来一个完整的实战例子。假设我们要做一个后台管理系统,结构是这样的:

路径 组件 说明
/admin AdminLayout 后台主布局,包含侧边栏和内容区
/admin/dashboard Dashboard 仪表盘,默认首页
/admin/users UserList 用户列表
/admin/users/:id UserDetail 用户详情
/admin/settings Settings 系统设置

路由配置如下:

const routes = [
  {
    path: '/admin',
    component: AdminLayout,
    children: [
      {
        path: '',
        redirect: '/admin/dashboard'
      },
      {
        path: 'dashboard',
        component: Dashboard
      },
      {
        path: 'users',
        component: UserList
      },
      {
        path: 'users/:id',
        component: UserDetail
      },
      {
        path: 'settings',
        component: Settings
      }
    ]
  }
]

这里我用了 redirect 来做默认跳转。访问 /admin 时,自动跳到 /admin/dashboard。这种做法很常见,省得用户看到空白页面。

核心要点:
  • children 里的 path 不要加 / 前缀
  • 每一层嵌套都要有对应的 <router-view>
  • 命名视图用 components(复数)配置
  • 嵌套层级建议不超过三层
  • 用 redirect 处理默认子路由

我曾经在一个项目里,因为没注意 children 的 path 写法,导致路由死活不生效。排查了半天,才发现是多了个 /。从那以后,我写嵌套路由都会先检查 path 的格式。

嵌套路由和命名视图,说白了就是 Vue Router 给我们的两个布局利器。一个管纵向的层级关系,一个管横向的区域划分。结合起来用,大部分后台系统的路由需求都能搞定。