layout 是包装多个页面的共享 UI,并且在导航过程中持久存在 — 当你在子路由之间移动时,它不会重新渲染或丢失状态。你可以用 layout.tsx 文件定义它。
根布局(必需)
tsx
() {
(
);
}
layout 是包装多个页面的共享 UI,并且在导航过程中持久存在 — 当你在子路由之间移动时,它不会重新渲染或丢失状态。你可以用 layout.tsx 文件定义它。
() {
(
);
}
每个 App Router 应用都必须有一个根布局 — 它取代了旧的 _app.tsx/_document.tsx。
布局沿着文件夹结构嵌套,所以每个部分都可以添加自己的持久包装器:
app/layout.tsx → wraps everything (header/footer)
app/dashboard/layout.tsx → wraps all /dashboard/* pages (adds a sidebar)
app/dashboard/settings/page.tsx → rendered inside BOTH layouts
// app/dashboard/layout.tsx — only wraps dashboard routes
export default function DashboardLayout({ children }) {
return (
<div className="flex">
<Sidebar /> {/* stays mounted as you move within /dashboard */}
<main>{children}</main>
</div>
);
}
当你从 /dashboard/settings 导航到 /dashboard/billing 时,仪表板布局(及其 <Sidebar>)保持挂载 — 它的状态(滚动位置、打开的菜单、表单输入)被保留,只有页面内容交换。这比重新渲染整个外壳更高效,并提供更流畅的用户体验。
// template.tsx — like layout but RE-mounts on every navigation (fresh state each time)
当你很少想要包装器在每次导航时重置时,使用 template.tsx 而不是 layout.tsx。
布局是 App Router 在路由树的任何级别建模共享、持久 UI(页眉、侧边栏、导航)的方式。
它们在导航过程中的持久性 — 保留状态并避免重新渲染外壳 — 是 App Router 的核心优势,嵌套布局让每个部分能够以简洁的方式组合自己的结构。