layout.js

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

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

根布局 (Root Layout) 是根目录 app 中最顶层的布局,用于定义 <html><body> 标签以及其他全局共享的用户界面。

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 的公共布局:

文件结构展示了一个 dashboard 文件夹嵌套了 layout.tsx 文件,以及 settings 和 analytics 文件夹各自包含页面文件

当从 /dashboard/settings 导航到 /dashboard/analytics 时,/dashboard/analytics 中的 page.tsx 会在服务器端重新渲染,而 dashboard/layout.tsx 不会 重新渲染,因为它是两个路由共享的用户界面。

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

由于 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