Learn Next.js 官方教學筆記 - Chapter 4 : Creating Layouts and Pages
此系列為 Next.js 官方教學 Learn Next.js 的筆記。
文章連結:Chapter 4 : Creating Layouts and Pages。
到目前為止,應用程式中只有首頁。接下來讓我們來學習如何利用 layouts 以及 pages 來創建更多 routes。
在這一章節可以學到以下幾個項目
- 利用檔案結構的 routing 來創建
dashboard
的 routes。 - 了解在建立新 route 的時候,資料節及檔案的角色。
- 創建可以在多個 dashboard 頁面共享的 nested layout。
- 了解部分渲染以及 root layout。
Nested routing
Next.js 是基於檔案的結構中的資料夾來定義 URL 路徑的。每個資料夾都代表 route segment 對應 URL segment。
也就是說可以透過 layout.tsx
以及 page.tsx
來創建獨立的 UI。
page.tsx
是一個 Next.js 特別的檔案,它導出一個 React component,來讓 route 可以訪問它。而在目前的應用程式中,已經有了一個 page file : /app/page.tsx
,這讓首頁可以藉由 route /
來訪問。
所以想要創建一個 nested route,你可以彼此的巢狀資料夾結構,並在其中加入 page.tsx 檔案。比方說:
以上圖片代表 /app/dashboard/page.tsx
可以藉由 /dashboard
路徑訪問。
Creating the dashboard page
在資料夾路徑 /app
中創建一個資料夾 dashboard
。然後在裡面創建一個新檔案 page.tsx
並輸入以下內容:
export default function Page() {
return <p>Dashboard Page</p>;
}
接下來可以跑跑看自己的程式,可以發現在 http://localhost:3000/dashboard 的內容。
這是在 Next.js 中可以藉由資料夾以及 page
檔案創建路由的方式。
而藉由page 這個檔案,可以讓你在路由裡整合 UI 元件、測試檔案以及其他在這個路由的相關程式。而且就算檔案夾有其他檔案,也只有 page 這個檔案的內容會被訪問。
Practice: Creating the dashboard pages
試試看建立更多 routes。在 dashboard 中建立兩個頁面:
- Customers Page:
- 可以在 http://localhost:3000/dashboard/customers 被訪問。並回傳一個
<p>Customers Page</p>
元素。
- 可以在 http://localhost:3000/dashboard/customers 被訪問。並回傳一個
- Invoices Page:
- 可以在 http://localhost:3000/dashboard/invoices 被訪問。並回傳一個
<p>Invoices Page</p>
元素。
- 可以在 http://localhost:3000/dashboard/invoices 被訪問。並回傳一個
Solution:
以下是檔案的結構
Customers Page:
export default function Page() { return <p>Customers Page</p>; }
Invoices Page:
export default function Page() { return <p>Invoices Page</p>; }
Creating the dashboard layout
在 dashboards 中會有一個讓多個頁面共享的 navigation。在 Next.js 中,你可以使用特別的 layout.tsx
檔案來建立可以被多頁面共享的 UI。
方法是在 /dashboard
的資料夾中,新增一個叫 layout.tsx
的檔案,並把下列內容貼上:
import SideNav from '@/app/ui/dashboard/sidenav';
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
<div className="w-full flex-none md:w-64">
<SideNav />
</div>
<div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
</div>
);
}
完成之後會有一些變化,接下來就來說明說明:
首先,在這個檔案開頭有 import 一個 <SideNav />
元件到 layout 中。而任何被 import 到這裡的都會是 layout 的一部分。
<Layout />
component 會接收一個 children
的 prop。這個 child可以是一個頁面或是另一個 layout。而在這個例子中,在 /dashboard
的頁面會自動被放置在 <Layout />
中,像以下這樣:
若以上都沒問題,應該會有下面的頁面:
一個在 Next.js 的 navigation 使用 layouts 的好處是,當 page 元件更新時,layout 元件並不會重新渲染。這樣就叫做 Partial rendering。
Root layout
在 Chapter 3 的時候,有使用 Inter 字型到另一個 layout :/app/layout.tsx
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={`${inter.className} antialiased`}>{children}</body>
</html>
);
}
這個叫做 root layout ,並且是必須要有的。而任何被加進 root layout 的 UI 都會被應用程式中的所有頁面共享。所以你可以使用 root layout 來更改 <html>
以及 <body>
tags,並加入 metadata。
而因為剛剛建立的 UI(/app/dashboard/layout.tsx
)是 dashboard 頁面獨有的,所以並不需要新增任何 UI 到 root layout 中。