頁面間導航
在前一章中,您建立了儀表板佈局和頁面。現在,讓我們添加一些連結,讓使用者能在儀表板路由之間導航。
為何要優化導航?
傳統上,您會使用 <a>
HTML 元素來連結頁面。目前側邊欄連結使用了 <a>
元素,但請注意當您在瀏覽器中導航至首頁、發票和客戶頁面時會發生什麼。
您注意到了嗎?
每次頁面導航都會觸發完整的頁面重新載入!
<Link>
元件
在 Next.js 中,您可以使用 <Link />
元件來連結應用程式中的頁面。<Link>
允許您透過 JavaScript 進行客戶端導航。
要使用 <Link />
元件,請開啟 /app/ui/dashboard/nav-links.tsx
,並從 next/link
匯入 Link
元件。然後,將 <a>
標籤替換為 <Link>
:
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
// ...
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
如您所見,Link
元件的使用方式與 <a>
標籤類似,但您使用 <Link href="…">
而非 <a href="…">
。
儲存變更並檢查本地主機上的效果。您現在應該能在頁面之間導航而不會看到完整重新載入。儘管應用程式的部分內容是在伺服器端渲染的,但沒有完整的頁面重新載入,使其感覺像是原生網頁應用程式。這是為什麼呢?
自動程式碼分割與預取
為了改善導航體驗,Next.js 會根據路由段自動進行程式碼分割。這與傳統的 React 單頁應用程式 (SPA) 不同,後者會在初始頁面載入時載入所有應用程式程式碼。
按路由分割程式碼意味著頁面是隔離的。如果某個頁面發生錯誤,應用程式的其餘部分仍能正常運作。這也減少了瀏覽器需要解析的程式碼量,使您的應用程式更快。
此外,在生產環境中,每當 <Link>
元件出現在瀏覽器的視窗中時,Next.js 會自動在背景預取連結路由的程式碼。當使用者點擊連結時,目標頁面的程式碼已經在背景載入完畢,這就是頁面轉換幾乎瞬間完成的原因!
深入了解導航運作原理。
模式:顯示當前連結
一個常見的 UI 模式是顯示當前連結,以告知使用者他們所在的頁面。為此,您需要從 URL 中取得使用者的當前路徑。Next.js 提供了一個名為 usePathname()
的鉤子,您可以用來檢查路徑並實現此模式。
由於 usePathname()
是一個 React 鉤子,您需要將 nav-links.tsx
轉換為客戶端元件。在檔案頂部添加 React 的 "use client"
指令,然後從 next/navigation
匯入 usePathname()
:
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
// ...
接下來,在 <NavLinks />
元件內部將路徑賦值給一個名為 pathname
的變數:
export default function NavLinks() {
const pathname = usePathname();
// ...
}
注意:
nav-links.tsx
並非 Next.js 的特殊檔案 — 它可以隨意命名。如果您重新命名,請確保相應地更新匯入語句。
您可以使用在 CSS 樣式 章節中介紹的 clsx
函式庫,根據連結是否處於活動狀態來條件式套用類別名稱。當 link.href
與 pathname
匹配時,連結應顯示為藍色文字和淺藍色背景。
以下是 nav-links.tsx
的最終程式碼:
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
// ...
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
{
'bg-sky-100 text-blue-600': pathname === link.href,
},
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
儲存並檢查本地主機上的效果。您現在應該能看到當前連結以藍色高亮顯示。