Next.js Layouts 與 Templates

在構建應用程式時,導航欄、側邊欄或頁腳通常是多個頁面共用的。Next.js 提供了 Layouts 和 Templates 兩種檔案慣例來處理這些共享 UI。

Layouts (佈局)

Layout 是指在多個路由之間共享的 UI。當使用者在子路由之間導航時,Layout 會被保留,不會重新渲染 (Re-render),這使得它非常適合存放導航列或搜尋框,因為它能保留輸入框內容或捲動位置。

如何定義 Layout?

在任何路由目錄下建立 layout.tsx,該佈局將自動應用於該目錄及其所有子目錄。

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children, // 代表子頁面或子佈局
}: {
  children: React.ReactNode;
}) {
  return (
    <section className="flex">
      <nav className="w-64 bg-gray-100 p-4">
        {/* 指向 /dashboard, /dashboard/settings 等 */}
        <ul>
          <li>首頁</li>
          <li>設定</li>
        </ul>
      </nav>
      <div className="flex-1 p-8">{children}</div>
    </section>
  );
}

Layout 的特性:

  • 狀態保留:導覽時不會丟失 React State。
  • 巢狀結構:子目錄的 Layout 會被包在父目錄的 Layout 裡面。
  • 不支援重新載入動畫:因為它不會重新掛載,所以 CSS 動畫可能不會重複播放。

Templates (模板)

Template 的功能與 Layout 類似,但他有一個核心差異:當使用者切換路由時,Template 會為每個子路由建立一個全新的實例

這意味著當你在路由之間導航時:

  1. DOM 元素會被重新建立。
  2. 狀態 (State) 不會被保留。
  3. Effects 會重新執行。

為什麼需要 Template?

通常在以下特定場景,你會選擇使用 Template 而非 Layout:

  • CSS 動畫:如果你希望每次切換頁面時都有進場動畫 (Enter/Exit animations)。
  • useEffect 依賴:當你需要在導航時重置某些追蹤邏輯或重新訂閱。

如何使用 Template?

檔名必須為 template.tsx

// app/dashboard/template.tsx
'use client';

import { useEffect } from 'react';

export default function Template({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    console.log('頁面已切換,Template 重新初始化');
  }, []);

  return <div>{children}</div>;
}

Layout 與 Template 並存時的行為

你可能會好奇,如果在同一個資料夾下同時建立了 layout.tsxtemplate.tsx,它們會如何運作?

答案是:它們可以共存,且有固定的包裹順序。

當兩者同時存在時,Next.js 會將 Template 包裹在 Layout 裡面,結構如下:

<Layout>
  <Template>
    {/* Page 內容 */}
    <Page />
  </Template>
</Layout>

這意味著:

  1. Layout 負責「持久化」:最外層的 UI (Layout) 在導航時保持不變,狀態保留。
  2. Template 負責「重置」:內層的 UI (Template) 在每次導航時都會重新建立。

這種模式非常實用。例如,你可以使用 layout.tsx 來放置不會變動的側邊欄導航,同時使用 template.tsx 來包裹頁面內容,以便在每次切換頁面時觸發淡入淡出 (Fade-in) 的動畫效果。

Layout vs Template 比較

特性LayoutTemplate
重新渲染導覽時不重新渲染導覽時重新掛載 (Re-mount)
狀態保留是 (保留內容、捲動位置)否 (狀態被重置)
效能較佳效能略遜 (因需重建 DOM)
適用場景大部分共享 UI進場動畫、重置狀態

總結

在 Next.js 中,預設情況下你應該始終使用 Layout。只有當你明確需要「每次導覽都重置狀態」或「每次都要播放動畫」時,才考慮使用 Template。

這種精細的控制讓你在開發時,能根據效能與使用者體驗做出最佳的設計抉擇。