Link
<Link>
是一個擴展 HTML <a>
元素的 React 元件,提供 預取 (prefetching) 和路由間的客戶端導航功能。它是 Next.js 中在路由之間導航的主要方式。
基本用法:
參考
以下屬性可以傳遞給 <Link>
元件:
屬性 | 範例 | 類型 | 必填 |
---|---|---|---|
href | href="/dashboard" | 字串或物件 | 是 |
replace | replace={false} | 布林值 | - |
scroll | scroll={false} | 布林值 | - |
prefetch | prefetch={false} | 布林值或 null | - |
onNavigate | onNavigate={(e) => {}} | 函式 | - |
須知:可以將
<a>
標籤屬性(如className
或target="_blank"
)作為屬性添加到<Link>
,這些屬性將傳遞給底層的<a>
元素。
href
(必填)
要導航到的路徑或 URL。
replace
預設為 false
。 當設為 true
時,next/link
會替換當前的歷史狀態,而不是在 瀏覽器的歷史記錄 堆疊中添加一個新的 URL。
scroll
預設為 true
。 Next.js 中 <Link>
的預設滾動行為是 保持滾動位置,類似於瀏覽器處理前進和後退導航的方式。當您導航到新的 頁面 (Page) 時,只要該頁面在視口中可見,滾動位置將保持不變。但是,如果頁面不在視口中,Next.js 會滾動到第一個頁面元素的頂部。
當 scroll = {false}
時,Next.js 不會嘗試滾動到第一個頁面元素。
須知:Next.js 在管理滾動行為之前會檢查
scroll: false
。如果滾動已啟用,它會識別導航的相關 DOM 節點並檢查每個頂層元素。所有不可滾動的元素和沒有渲染 HTML 的元素都會被跳過,這包括固定或絕對定位的元素,以及使用getBoundingClientRect
計算的非可見元素。Next.js 然後繼續檢查兄弟元素,直到識別出視口中可見的可滾動元素。
prefetch
當 <Link />
元件進入用戶的視口(初始或通過滾動)時,預取會發生。Next.js 會在後台預取並加載連結的路由(由 href
表示)及其數據,以提高客戶端導航的性能。如果用戶懸停在 <Link />
上時預取的數據已過期,Next.js 將嘗試再次預取。預取僅在生產環境中啟用。
可以傳遞給 prefetch
屬性的值如下:
null
(預設):預取行為取決於路由是靜態還是動態。對於靜態路由,將預取完整路由(包括所有數據)。對於動態路由,將預取到最近的loading.js
邊界的部分路由。true
:對於靜態和動態路由,都會預取完整路由。false
:無論是進入視口還是懸停,都不會發生預取。
onNavigate
在客戶端導航期間調用的事件處理程序。該處理程序接收一個事件對象,其中包括 preventDefault()
方法,允許您在需要時取消導航。
須知:雖然
onClick
和onNavigate
看起來相似,但它們有不同的用途。onClick
執行所有點擊事件,而onNavigate
僅在客戶端導航期間運行。一些關鍵區別:
- 當使用修飾鍵(
Ctrl
/Cmd
+ 點擊)時,onClick
會執行但onNavigate
不會,因為 Next.js 會阻止新標籤的預設導航。- 外部 URL 不會觸發
onNavigate
,因為它僅用於客戶端和同源導航。- 帶有
download
屬性的連結會與onClick
一起工作,但不會與onNavigate
一起工作,因為瀏覽器會將連結的 URL 視為下載。
範例
以下範例演示瞭如何在不同的場景中使用 <Link>
元件。
連結到動態區段
當連結到 動態區段 (dynamic segments) 時,您可以使用 模板字面量和插值 (template literals and interpolation) 來生成連結列表。例如,生成部落格文章列表:
檢查當前活動連結
您可以使用 usePathname()
來判斷連結是否處於活動狀態。例如,要為當前活動連結添加 class,您可以檢查當前 pathname
是否與連結的 href
匹配:
滾動至特定 id
如果您想在導航時滾動至特定 id
,可以在 URL 後附加 #
雜湊連結,或直接將雜湊連結傳遞給 href
屬性。這是可行的,因為 <Link>
最終會渲染為 <a>
元素。
須知:
- 如果導航時 Page 不在視窗可見範圍內,Next.js 會自動滾動至該頁面。
連結至動態路由區段
對於 動態路由區段 (dynamic route segments),使用模板字面值來建立連結路徑會非常方便。
例如,您可以生成一個連結列表,指向動態路由 app/blog/[slug]/page.js
:
當子元件是包裝 <a>
標籤的自訂元件時
如果 Link
的子元件是一個包裝 <a>
標籤的自訂元件,您必須在 Link
上添加 passHref
。當您使用像 styled-components 這樣的函式庫時,這點尤其重要。如果不這樣做,<a>
標籤將不會有 href
屬性,這會影響網站的無障礙性和 SEO。如果您使用 ESLint,內建的 next/link-passhref
規則可以確保正確使用 passHref
。
- 如果您使用 emotion 的 JSX pragma 功能 (
@jsx jsx
),即使直接使用<a>
標籤,也必須使用passHref
。 - 元件應支援
onClick
屬性以正確觸發導航。
嵌套函式元件
如果 Link
的子元件是一個函式元件,除了使用 passHref
和 legacyBehavior
外,您還必須使用 React.forwardRef
包裝該元件:
替換 URL 而非推送
Link
元件的預設行為是將新 URL push
到 history
堆疊中。您可以使用 replace
屬性來避免添加新條目,如下例所示:
禁用滾動至頁面頂部
Next.js 中 <Link>
的預設滾動行為是保持滾動位置,類似於瀏覽器處理前進和後退導航的方式。當您導航至新的 Page 時,只要該頁面在視窗中可見,滾動位置將保持不變。
但是,如果頁面不在視窗的可見範圍內,Next.js 會滾動至第一個頁面元素的頂部。如果您想禁用此行為,可以將 scroll={false}
傳遞給 <Link>
元件,或將 scroll: false
傳遞給 router.push()
或 router.replace()
。
使用 router.push()
或 router.replace()
:
在中間層 (Middleware) 中預取連結
常見的做法是使用中間層 (Middleware)來處理驗證或其他需要將使用者重新導向到不同頁面的情況。為了讓 <Link />
元件能正確預取透過中間層重寫的連結,你需要告訴 Next.js 要顯示的 URL 和要預取的 URL。這是為了避免不必要的向中間層發送請求來確認要預取的正確路由。
例如,如果你想提供一個具有已驗證和訪客視圖的 /dashboard
路由,可以在你的中間層中添加以下內容來將使用者重定向到正確的頁面:
在這種情況下,你需要在 <Link />
元件中使用以下程式碼:
阻止導航
你可以使用 onNavigate
屬性在某些條件滿足時阻止導航,例如當表單有未儲存的變更時。當你需要在應用程式的多個元件中阻止導航(例如在編輯表單時阻止從任何連結導航),React Context 提供了一種乾淨的方式來共享這個阻止狀態。首先,建立一個上下文來追蹤導航阻止狀態:
建立一個使用該上下文的表單元件:
建立一個自訂的 Link 元件來阻止導航:
建立一個導航元件:
最後,在根佈局中用 NavigationBlockerProvider
包裹你的應用程式,並在頁面中使用這些元件:
然後,在頁面中使用 Nav
和 Form
元件:
當使用者嘗試在表單有未儲存的變更時使用 CustomLink
導航時,系統會提示他們確認是否離開。
版本歷史
版本 | 變更 |
---|---|
v15.3.0 | 新增 onNavigate API |
v13.0.0 | 不再需要子 <a> 標籤。提供了一個程式碼修改工具 (codemod) 來自動更新你的程式碼庫。 |
v10.0.0 | 指向動態路由的 href 屬性會自動解析,不再需要 as 屬性。 |
v8.0.0 | 改進了預取效能。 |
v1.0.0 | 引入 next/link 。 |