链接和导航
在Next.js中,有两种在路由之间导航的方式:
- 使用
<Link>
组件 - 使用
useRouter
Hook
本页面将介绍如何使用 <Link>
、useRouter()
,并深入探讨导航的工作原理。
<Link>
组件
<Link>
是一个内置组件,它扩展了 HTML 的 <a>
标签,
提供了在路由之间进行预取和客户端导航的功能。
这是在Next.js中导航之间的主要方式。
您可以通过从 next/link
中导入它,并向组件传递一个 href
属性来使用它:
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
还可以向 <Link>
传递其他可选的属性。更多信息请参阅 API 参考。
示例
链接到动态段
在链接到动态段时,您可以使用模板文字和插值来生成链接列表。例如,要生成博客文章列表:
import Link from 'next/link'
export default function PostList({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
检查活动链接
您可以使用 usePathname()
来确定链接是否处于活动状态。
例如,要向活动链接添加类,您可以检查当前pathname
是否与链接的 href
匹配:
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Links() {
const pathname = usePathname()
return (
<nav>
<ul>
<li>
<Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
Home
</Link>
</li>
<li>
<Link
className={`link ${pathname === '/about' ? 'active' : ''}`}
href="/about"
>
About
</Link>
</li>
</ul>
</nav>
)
}
滚动到id
Next.js App Router 的默认行为是在导航时滚动到新路由的顶部,或者对于后退和前进导航保持滚动位置。
如果您想要在导航时滚动到特定的标识,可以在URL后附加一个 #
锚链接,
或者只是将一个 #
锚链接传递给 href
属性。这是因为 <Link>
渲染为 <a>
元素,所以是可能的。
<Link href="/dashboard#settings">Settings</Link>
// 输出
<a href="/dashboard#settings">Settings</a>
禁用滚动恢复
Next.js App Router 的默认行为是在导航时滚动到新路由的顶部,或者对于后退和前进导航保持滚动位置。
如果您想要禁用此行为,可以将 scroll={false}
传递给 <Link>
组件,
或者将 scroll: false
传递给 router.push()
或 router.replace()
。
// next/link
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
// useRouter
import { useRouter } from 'next/navigation'
const router = useRouter()
router.push('/dashboard', { scroll: false })
useRouter()
Hook
useRouter
钩子允许您以编程方式更改路由。
此钩子只能在客户端组件内使用,并且是从 next/navigation
导入的。
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
有关 useRouter
方法的完整列表,请参阅 API 参考。
除非有使用 useRouter
的特定需求,否则请使用 <Link>
组件在路由之间进行导航。
路由和导航的工作原理
App Router 使用混合方法进行路由和导航。 在服务器上,您的应用程序代码会自动按路由段进行代码拆分。 在客户端上,Next.js 会预取和缓存路由段。 这意味着当用户导航到新路由时,浏览器不会重新加载页面,只有更改的路由段会重新渲染, 从而提高导航体验和性能。
- 预取 预取是在用户访问之前在后台预加载路由的一种方式。
在Next.js中,有两种路由的预取方式:
<Link>
组件:路由在用户视口中变得可见时会自动进行预取。预取发生在页面首次加载时或通过滚动进入视图时。router.prefetch()
:可以使用useRouter
钩子以编程方式进行路由的预取。
对于<Link>
的预取行为在
静态和动态路由上是不同的:
- 静态路由:
prefetch
默认为true
。整个路由将被预取和缓存。 - 动态路由:
prefetch
默认为automatic
。 只有共享布局直到第一个loading.js
文件的路由段被预取和缓存,缓存有效期为30秒。 这降低了获取整个动态路由的成本,并且您可以显示即时的加载状态,以提供更好的视觉反馈。
您可以通过将 prefetch
属性设置为 false
来禁用预取。
有关更多信息,请参阅 <Link>
API 参考。
prefetch
在开发中未启用,只在生产中启用。
- 缓存 Next.js具有一个内存中的客户端端缓存, 称为Router Cache。 当用户在应用程序中导航时, 预取 路由段和访问过的路由的React Server Component Payload都存储在缓存中。
这意味着在导航时,尽可能地重用缓存,而不是向服务器发出新请求, 从而通过减少请求和数据传输的次数来提高性能。
了解有关Router Cache 如何工作以及如何配置它的更多信息。
- 部分渲染 部分渲染意味着在客户端上只重新渲染在导航时发生变化的路由段,而保留任何共享段。
例如,在两个兄弟路由之间导航,/dashboard/settings
和 /dashboard/analytics
,
将呈现settings
和analytics
,并保留共享的仪表板布局。
如果没有部分渲染,每次导航都会导致在服务器上重新渲染整个页面。 只渲染发生变化的段减少了传输的数据量和执行时间,从而提高了性能。
-
软导航 默认情况下,浏览器在页面之间执行硬导航。 这意味着浏览器重新加载页面并重置React状态,例如应用程序中的
useState
钩子和浏览器状态, 例如用户的滚动位置或焦点元素。 然而,在Next.js中,App Router 使用软导航。 这意味着React仅渲染更改的段 ,同时保留React和浏览器状态,而没有完全重新加载页面。 -
后退和前进导航 默认情况下,Next.js会保持后退和前进导航的滚动位置, 并在Router Cache 中重新使用路由段。