頁面與佈局
Next.js 13 中的 App Router 引入了新的檔案慣例,可輕鬆建立頁面、共享佈局和模板。本頁將指導您如何在 Next.js 應用程式中使用這些特殊檔案。
頁面
頁面是路由中獨特的使用者介面。您可以透過從 page.js
檔案匯出元件來定義頁面。使用巢狀資料夾來定義路由,並使用 page.js
檔案使路由可公開存取。
在 app
目錄中新增 page.js
檔案來建立您的第一個頁面:

// `app/page.tsx` 是 `/` URL 的使用者介面
export default function Page() {
return <h1>Hello, Home page!</h1>
}
// `app/page.js` 是 `/` URL 的使用者介面
export default function Page() {
return <h1>Hello, Home page!</h1>
}
// `app/dashboard/page.tsx` 是 `/dashboard` URL 的使用者介面
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
// `app/dashboard/page.js` 是 `/dashboard` URL 的使用者介面
export default function Page() {
return <h1>Hello, Dashboard Page!</h1>
}
須知事項:
佈局
佈局是多個頁面之間共享的使用者介面。在導航時,佈局會保留狀態、保持互動性且不會重新渲染。佈局也可以巢狀。
您可以透過從 layout.js
檔案 default
匯出 React 元件來定義佈局。該元件應接受 children
prop,該 prop 會在渲染時填入子佈局(如果存在)或子頁面。

export default function DashboardLayout({
children, // 將是頁面或巢狀佈局
}: {
children: React.ReactNode
}) {
return (
<section>
{/* 在此包含共享 UI,例如標頭或側邊欄 */}
<nav></nav>
{children}
</section>
)
}
export default function DashboardLayout({
children, // 將是頁面或巢狀佈局
}) {
return (
<section>
{/* 在此包含共享 UI,例如標頭或側邊欄 */}
<nav></nav>
{children}
</section>
)
}
須知事項:
- 最頂層的佈局稱為根佈局。此必需佈局在應用程式的所有頁面中共享。根佈局必須包含
html
和body
標籤。- 任何路由區段都可以選擇性地定義自己的佈局。這些佈局將在該區段的所有頁面中共享。
- 路由中的佈局預設為巢狀。每個父佈局使用 React
children
prop 包裝其下方的子佈局。- 您可以使用路由群組來選擇特定路由區段加入或退出共享佈局。
- 佈局預設為伺服器元件,但可以設為客戶端元件。
- 佈局可以取得資料。請參閱資料取得章節以取得更多資訊。
- 無法在父佈局與其子元件之間傳遞資料。但是,您可以在路由中多次取得相同的資料,React 會自動去重複請求而不影響效能。
- 佈局無法存取其下方的路由區段。要存取所有路由區段,可以在客戶端元件中使用
useSelectedLayoutSegment
或useSelectedLayoutSegments
。- 佈局可以使用
.js
、.jsx
或.tsx
副檔名。- 可以在同一資料夾中定義
layout.js
和page.js
檔案。佈局將包裝頁面。
根佈局 (必需)
根佈局定義在 app
目錄的頂層,適用於所有路由。此佈局讓您可以修改從伺服器返回的初始 HTML。
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
須知事項:
從
pages
目錄遷移: 根佈局取代了_app.js
和_document.js
檔案。查看遷移指南。
巢狀佈局
定義在資料夾內的佈局(例如 app/dashboard/layout.js
)適用於特定路由區段(例如 acme.com/dashboard
),並在這些區段處於活動狀態時渲染。預設情況下,檔案層級中的佈局是巢狀的,這意味著它們透過 children
prop 包裝子佈局。

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
須知事項:
- 只有根佈局可以包含
<html>
和<body>
標籤。
如果您將上述兩個佈局結合,根佈局 (app/layout.js
) 將包裝儀表板佈局 (app/dashboard/layout.js
),而儀表板佈局將包裝 app/dashboard/*
內的路由區段。
這兩個佈局將如下巢狀:

您可以使用路由群組來選擇特定路由區段加入或退出共享佈局。
模板
模板與佈局類似,它們包裝每個子佈局或頁面。與跨路由保留狀態的佈局不同,模板在導航時會為每個子元件建立新實例。這意味著當使用者在共享模板的路由之間導航時,會掛載元件的新實例、重新建立 DOM 元素、不會保留狀態,且效果會重新同步。
在某些情況下,您可能需要這些特定行為,這時模板會是比佈局更合適的選擇。例如:
- 依賴
useEffect
的功能(例如記錄頁面瀏覽)和useState
(例如每頁的反饋表單)。 - 變更框架的預設行為。例如,佈局內的 Suspense Boundaries 僅在佈局首次載入時顯示後備內容,而在切換頁面時不會顯示。對於模板,後備內容會在每次導航時顯示。
可以透過從 template.js
檔案匯出預設 React 元件來定義模板。該元件應接受 children
prop。

export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
export default function Template({ children }) {
return <div>{children}</div>
}
在巢狀結構方面,template.js
會在佈局與其子元件之間渲染。以下是簡化的輸出:
<Layout>
{/* 請注意模板具有唯一鍵。 */}
<Template key={routeParam}>{children}</Template>
</Layout>
修改 <head>
在 app
目錄中,您可以使用內建 SEO 支援來修改 <head>
HTML 元素,例如 title
和 meta
。
可以在 layout.js
或 page.js
檔案中匯出 metadata
物件 或 generateMetadata
函式 來定義元資料。
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
export const metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
須知事項:您不應手動將
<head>
標籤(例如<title>
和<meta>
)新增至根佈局。相反,您應使用元資料 API,它會自動處理進階需求,例如串流和去重複<head>
元素。