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。

Image.png

也就是說可以透過 layout.tsx 以及 page.tsx 來創建獨立的 UI。

page.tsx 是一個 Next.js 特別的檔案,它導出一個 React component,來讓 route 可以訪問它。而在目前的應用程式中,已經有了一個 page file : /app/page.tsx ,這讓首頁可以藉由 route / 來訪問。

所以想要創建一個 nested route,你可以彼此的巢狀資料夾結構,並在其中加入 page.tsx 檔案。比方說:

Image.png

以上圖片代表 /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 中建立兩個頁面:

  1. Customers Page:
  2. Invoices Page:
  3. Solution:

    以下是檔案的結構

Image.png

  • 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 /> 中,像以下這樣:

Image.png

若以上都沒問題,應該會有下面的頁面:

Image.png

一個在 Next.js 的 navigation 使用 layouts 的好處是,當 page 元件更新時,layout 元件並不會重新渲染。這樣就叫做 Partial rendering

Image.png

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 中。