頁面與佈局

建議先閱讀路由基礎定義路由頁面再繼續。

特殊檔案 layout.jspage.jstemplate.js 可讓您為路由建立使用者介面。本頁將指導您如何使用這些特殊檔案及其適用時機。

頁面

頁面是路由專屬的使用者介面。您可以透過從 page.js 檔案預設匯出元件來定義頁面。

例如,要建立 index 頁面,請在 app 目錄中新增 page.js 檔案:

page.js 特殊檔案
// `app/page.tsx` 是 `/` URL 的使用者介面
export default function Page() {
  return <h1>Hello, Home page!</h1>
}

接著,要建立更多頁面,請新增一個資料夾並在其中新增 page.js 檔案。例如,要為 /dashboard 路由建立頁面,請建立名為 dashboard 的新資料夾,並在其中新增 page.js 檔案:

// `app/dashboard/page.tsx` 是 `/dashboard` URL 的使用者介面
export default function Page() {
  return <h1>Hello, Dashboard Page!</h1>
}

須知事項

佈局

佈局是多個路由之間共享的使用者介面。在導航時,佈局會保留狀態、保持互動性且不會重新渲染。佈局也可嵌套

您可以透過從 layout.js 檔案預設匯出 React 元件來定義佈局。該元件應接受 children 屬性,在渲染時會填入子佈局(如果存在)或頁面。

例如,以下佈局將與 /dashboard/dashboard/settings 頁面共享:

layout.js 特殊檔案
export default function DashboardLayout({
  children, // 將是頁面或嵌套佈局
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      {/* 在此包含共享 UI,例如標頭或側邊欄 */}
      <nav></nav>

      {children}
    </section>
  )
}

根佈局 (必要)

根佈局定義於 app 目錄的頂層,適用於所有路由。此佈局是必要的,且必須包含 htmlbody 標籤,讓您可以修改從伺服器返回的初始 HTML。

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

嵌套佈局

預設情況下,資料夾層級中的佈局是嵌套的,這意味著它們會透過 children 屬性包裹子佈局。您可以透過在特定路由區段(資料夾)中新增 layout.js 來嵌套佈局。

例如,要為 /dashboard 路由建立佈局,請在 dashboard 資料夾中新增 layout.js 檔案:

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

如果您將上述兩個佈局結合,根佈局 (app/layout.js) 會包裹儀表板佈局 (app/dashboard/layout.js),而儀表板佈局會包裹 app/dashboard/* 內的路由區段。

這兩個佈局的嵌套方式如下:

嵌套佈局 UI

須知事項

模板

模板與佈局類似,都會包裹每個子佈局或頁面。不同之處在於,佈局會跨路由保留狀態,而模板會在導航時為每個子元件建立新實例。這意味著當使用者在共享模板的路由之間導航時,會掛載元件的新實例、重新建立 DOM 元素、不會保留狀態,且會重新同步效果。

在某些情況下,您可能需要這些特定行為,此時模板會比佈局更適合。例如:

  • 依賴 useEffect 的功能(例如記錄頁面瀏覽)和 useState(例如每頁回饋表單)。
  • 變更預設框架行為。例如,佈局內的 Suspense Boundaries 僅在首次載入佈局時顯示後備內容,切換頁面時不會顯示。對於模板,每次導航都會顯示後備內容。

您可以透過從 template.js 檔案預設匯出 React 元件來定義模板。該元件應接受 children 屬性。

template.js 特殊檔案
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}

在嵌套方面,template.js 會在佈局與其子元件之間渲染。以下是簡化的輸出:

輸出
<Layout>
  {/* 注意模板具有唯一鍵。 */}
  <Template key={routeParam}>{children}</Template>
</Layout>

元數據

app 目錄中,您可以使用元數據 API (Metadata APIs) 修改 <head> HTML 元素,例如 titlemeta

您可以透過在 layout.jspage.js 檔案中匯出 metadata 物件generateMetadata 函式 來定義元數據。

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next.js',
}

export default function Page() {
  return '...'
}

須知事項:您不應手動新增 <head> 標籤(例如 <title><meta>)至根佈局。相反地,您應使用元數據 API (Metadata API),它會自動處理進階需求,例如串流和去重複 <head> 元素。

API 參考 中了解更多可用的元數據選項。

On this page