← [ BACK_TO_NOTES ]

Next.js Layouts

Next.js App Router 的 layout.tsx 为路由树提供可嵌套、可复用且在导航中保留的共享 UI 外壳,并可与 Route Groups 一起建立产品区域边界。

#concept #growing #frame #react

[!info] related notes

Next.js Layouts

一句话定义

layout.tsx 是 Next.js App Router 中某个路由层级的共享 UI 外壳;它包裹该 segment 及其子路由,并通过 children 插入当前子树内容。

RootLayout
└── AppLayout
    └── GoalsLayout
        └── GoalPage

核心机制

目录:

app/
├── layout.tsx
└── (app)/
    ├── layout.tsx
    ├── goals/page.tsx
    └── settings/page.tsx

(app)/layout.tsx 可以写成:

export default function AppLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div>
      <Sidebar />
      <main>{children}</main>
    </div>
  )
}

访问 /goals 时,children 是 Goals 页面;访问 /settings 时,children 换成 Settings 页面。

Layout 可以嵌套

每一层路由都可以增加自己的 layout.tsx:

app/layout.tsx
      ↓
(app)/layout.tsx
      ↓
goals/layout.tsx
      ↓
[goalId]/page.tsx

因此 App Router 的目录树同时也是一棵 UI Layout Tree。

Root Layout

app/layout.tsx 是最外层 Root Layout,负责应用最外层的 <html> 与 <body>:

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  )
}

全局主题、字体、Provider、全局导航等通常会从这里或其下层布局边界进入。

导航时为什么 Layout 很重要

共享 Layout 不只是“少复制一段 JSX”。App Router 导航时会复用仍然有效的父 Layout,而只替换变化的子路由内容。

AppLayout
├── Sidebar    ← 保留
├── Header     ← 保留
└── children
    ├── GoalsPage
    └── TasksPage

这意味着放在被保留的 Client Component Layout 中的局部状态,例如:

sidebarCollapsed = true

在 /goals → /tasks 这类共享同一 Layout 的导航中可以继续保留,而不必因为每次换页面都重新挂载外壳。

这类只更新发生变化部分的行为可以用 partial rendering 建立直觉。

Route Group + Layout

Next.js Route Groups 和 Layout 经常一起使用:

app/
├── (auth)/
│   ├── layout.tsx
│   ├── login/page.tsx
│   └── register/page.tsx
└── (app)/
    ├── layout.tsx
    ├── goals/page.tsx
    └── settings/page.tsx

这样:

  • (auth) 可以使用简单居中的认证布局。
  • (app) 可以使用 Sidebar + Topbar 的应用布局。
  • URL 仍然保持 /login、/goals,不会出现 /auth 或 /app。

所以 Route Group 不只是整理文件夹,也可以帮助定义稳定的 Layout Boundary。

Layout 与普通父组件的区别

普通父组件只是组件树的一部分;App Router Layout 还和路由树、导航复用与 segment 生命周期绑定。

因此:

普通 Parent Component
→ 组件复用

layout.tsx
→ 组件复用 + Route Tree Boundary + 导航时保留

边界与常见误区

Layout 不是权限系统

把页面放进 (app)/layout.tsx 不会自动代表“已登录”。认证和授权仍要显式实现。

Layout 不应该机械无限嵌套

只有确实共享稳定 UI 或需要独立路由边界时才值得增加一层 Layout。目录更深并不代表架构更专业。

同 segment 的 error.tsx 不会兜住该 segment 自己的 Layout 错误

错误边界包裹的是其子路由内容。如果错误发生在某个 layout.tsx 本身,需要更高一层的错误边界处理。见 Next.js Error Boundaries。

最短记忆方式

layout.tsx
= shared route shell
+ nested UI boundary
+ preserved parent during navigation

它主要回答:这一批 Route 之间,什么 UI 应该稳定存在并共享?

创建于 2026/9/15 更新于 2026/9/15
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本