← 路由设计 · 稳定入口与可变目标 / 嵌套路由 / layout · 一条 path 命中的不是一个,是一串 待审核 16 / 23

嵌套路由 / layout · 一条 path 命中的不是一个,是一串

匹配引擎里,一条 path 命中一条路由、得到一个 handler。真实前端(React Router、Vue Router、Next.js)的路由是一棵树:URL 的每一段对应树里的一层,一条 path 命中的是从根到叶的一整条链。链上每个节点都可以带一个 layout,它们层层嵌套地包住最终的页面——外层画框架(顶栏 / 侧边栏),内层在它留出的 outlet 槽位里渲染下一层。

这带来一个 path 平表给不了的性质:切换兄弟页面时,共享的外层 layout 原地不动。从 /dashboard/settings/profile 跳到 /billing\dots /billing,顶栏、侧边栏、设置页的标签条全部保持挂载(滚动位置、展开状态、输入都不丢),只有最内层那一格被换掉。下面点不同 path,看命中的链、看 layout 怎么嵌套,以及每次导航复用了哪几层、新挂了哪几层

复用,是嵌套路由最值钱的性质。/settings/profile\dots /settings/profile/settings/billing\dots /settings/billing 之间来回点:命中链的前三层(AppShellDashboardLayoutSettingsLayout完全相同,框架不卸载、不重建它们——侧边栏的展开状态、设置页标签条的位置都原样保留,只有最内层(ProfileBilling)被换下。上面每层的 ♻ 复用 / + 挂载 标签,标的就是这次导航相对上一次,哪几层活着、哪几层是新生的。

1 · index 路由:layout 自己那一格放什么

/dashboard 命中了 DashboardLayout,但 layout 只是个带 outlet 的框,它那一格该显示什么?答案是 index 路由——一条没有自己 path 段、专门填充父 layout 默认内容的子路由(React Router 的 index、Vue 的默认子路由)。所以 /dashboard 实际命中链是 AppShellDashboardLayout(index)OverviewAppShell \to DashboardLayout \to (index) Overview:三层,最后那层是 index。点 /dashboard 看这条链。

嵌套匹配把一条 path 走成一条「根 → 叶」的链:段段下行,缺段则取 index。

// 路由是一棵树; 一条 path 命中的是「根 → 叶」的一整条链。
function matchChain(node, segs) {
  if (segs.length === 0) {                    // 段吃完了
    const index = node.children?.find(c => c.index);
    return index ? [node, index] : [node];    // 有 index 子路由就补上它
  }
  for (const child of node.children ?? []) {
    if (child.index) continue;
    if (child.seg === segs[0]) {              // 这一段对上了
      const sub = matchChain(child, segs.slice(1));   // 继续往深处走
      if (sub) return [node, ...sub];
    }
  }
  return null;                                // 走不下去 → 404
}

// 渲染 = 把链上的 layout 从外到内嵌套, 每层在自己的 <Outlet/> 里放下一层:
//   AppShell( DashboardLayout( SettingsLayout( Profile )))
// 导航到兄弟页, 公共前缀的那几层不卸载 —— 这就是 layout 状态被保留的原因。

它和那台平表 matcher 是什么关系? 嵌套匹配可以展开成平表(把每条根 → 叶链拼成一条完整 pattern),匹配引擎页讲的 segment / 优先级规则照样适用。但树形写法多给了两样东西:layout 复用(上面那个性质,平表展开后就丢了);关注点分层——鉴权放 dashboard 层、设置页标签放 settings 层,各管一段,不必在每条叶子路由里重复。导航守卫也常按层挂:进入 dashboard 子树先过登录守卫,是这棵树上一条边的事。

2 · 相关页

  • 本系列 · 路由匹配引擎——嵌套链展开后就是那页讲的平表 pattern;segment 种类、顺序优先级在这里逐层适用,只是多了 layout 复用与分层。
  • 本系列 · 软导航 · 守卫——守卫常按树的层级挂载:进入某棵子树先过一道 guard。嵌套路由给了它天然的挂载点。
  • React Router · Nested Routes & Outlet——嵌套路由、<Outlet> 槽位、index 路由的官方模型——本页演示的就是它(Vue Router 的 children + router-view 同构)。