layout.js

布局 (Layout) 是指在多个路由间共享的用户界面。

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}

根布局 (Root Layout) 是位于根 app 目录下的最顶层布局,用于定义 <html><body> 标签以及其他全局共享的 UI 元素。

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

属性参数

children (必需)

布局组件应当接收并使用 children 属性。在渲染过程中,children 会被填充为该布局所包裹的路由片段。这些内容通常是子级 布局 (Layout)页面 (Page) 的组件(如果存在),但也可能是其他特殊文件如 加载状态 (Loading)错误处理 (Error)(当适用时)。

params (可选)

从根段到当前布局的 动态路由参数 (dynamic route parameters) 对象。

示例URLparams
app/dashboard/[team]/layout.js/dashboard/1{ team: '1' }
app/shop/[tag]/[item]/layout.js/shop/1/2{ tag: '1', item: '2' }
app/blog/[...slug]/layout.js/blog/1/2{ slug: ['1', '2'] }

示例:

export default function ShopLayout({
  children,
  params,
}: {
  children: React.ReactNode
  params: {
    tag: string
    item: string
  }
}) {
  // URL -> /shop/shoes/nike-air-max-97
  // `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
  return <section>{children}</section>
}

注意事项

布局不会接收 searchParams

页面 (Pages) 不同,布局组件 不会 接收 searchParams 属性。这是因为共享布局在 导航过程中不会重新渲染,可能导致导航间的 searchParams 数据过期。

使用客户端导航时,Next.js 会自动仅渲染两个路由间公共布局下方的页面部分。

例如,在以下目录结构中,dashboard/layout.tsx/dashboard/settings/dashboard/analytics 的公共布局:

app
└── dashboard
    ├── layout.tsx
    ├── settings
    │   └── page.tsx
    └── analytics
        └── page.js

当从 /dashboard/settings 导航到 /dashboard/analytics 时,/dashboard/analytics 中的 page.tsx 会在服务端渲染(因为它是变化的 UI),而 dashboard/layout.tsx 不会 重新渲染(因为它是两个路由间的公共 UI)。

这种性能优化使得共享布局的页面间导航更加快速,因为只需执行页面级别的数据获取和渲染,而无需处理可能包含自身数据获取的整个路由层级。

由于 dashboard/layout.tsx 不会重新渲染,布局中的 searchParams 属性在导航后可能会 过期

  • 替代方案:使用页面级的 searchParams 属性,或在客户端组件中使用 useSearchParams 钩子(该钩子会在客户端随最新的 searchParams 重新渲染)。

根布局特性

  • app 目录 必须 包含一个根级 app/layout.js 文件。
  • 根布局 必须 定义 <html><body> 标签。
    • 不应手动在根布局中添加 <head> 标签(如 <title><meta>),而应使用 元数据 API (Metadata API),它能自动处理流式传输和去重 <head> 元素等高级需求。
  • 可以使用 路由分组 (route groups) 创建多个根布局。
    • 跨多个根布局 的导航会触发 整页加载(而非客户端导航)。例如,从使用 app/(shop)/layout.js/cart 导航到使用 app/(marketing)/layout.js/blog 会触发整页加载。此规则 适用于多个根布局的情况。

版本历史

版本变更内容
v13.0.0引入 layout 功能。

On this page