Skip to main content

链接

<Link> 是一个 React 组件,它扩展了 HTML <a> 元素以提供 prefetching 和路由之间的客户端导航。这是在 Next.js 中的路由之间导航的主要方式。

¥<Link> is a React component that extends the HTML <a> element to provide prefetching and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.

import Link from 'next/link'

export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
import Link from 'next/link'

export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}

属性

¥Props

以下是链接组件可用的 props 的摘要:

¥Here's a summary of the props available for the Link Component:

属性示例类型必需的
hrefhref="/dashboard"字符串或对象是的
replacereplace={false}布尔值*
scrollscroll={false}布尔值*
prefetchprefetch={false}布尔值或空值*

很高兴知道:<a> 标签属性(例如 classNametarget="_blank")可以作为 props 添加到 <Link> 中,并将传递到底层 <a> 元素。

¥Good to know: <a> tag attributes such as className or target="_blank" can be added to <Link> as props and will be passed to the underlying <a> element.

href(必需的)

¥href (required)

要导航到的路径或 URL。

¥The path or URL to navigate to.

<Link href="/dashboard">Dashboard</Link>

href 也可以接受一个对象,例如:

¥href can also accept an object, for example:

// Navigate to /about?name=test
<Link
href={{
pathname: '/about',
query: { name: 'test' },
}}
>
About
</Link>

replace

默认为 false。当 true 时,next/link 会替换当前的历史状态,而不是在 浏览器的历史记录 堆栈中添加新的 URL。

¥Defaults to false. When true, next/link will replace the current history state instead of adding a new URL into the browser’s history stack.

import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" replace>
Dashboard
</Link>
)
}
import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" replace>
Dashboard
</Link>
)
}

scroll

默认为 true<Link> 的默认行为是滚动到新路由的顶部或保持滚动位置以进行向后和向前导航。当 falsenext/link 导航后不会滚动到页面顶部。

¥Defaults to true. The default behavior of <Link> is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation. When false, next/link will not scroll to the top of the page after a navigation.

import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
)
}
import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" scroll={false}>
Dashboard
</Link>
)
}

很高兴知道:

¥Good to know:

  • 如果导航时在视口中看不到 页面,Next.js 将滚动到 页面

    ¥Next.js will scroll to the Page if it is not visible in the viewport upon navigation.

prefetch

<Link /> 组件进入用户的视口(最初或通过滚动)时,会发生预取。Next.js 在后台预取并加载链接的路由(用 href 表示)及其数据,以提高客户端导航的性能。预取仅在生产中启用。

¥Prefetching happens when a <Link /> component enters the user's viewport (initially or through scroll). Next.js prefetches and loads the linked route (denoted by the href) and its data in the background to improve the performance of client-side navigations. Prefetching is only enabled in production.

  • null(默认):预取行为取决于路由是静态还是动态。对于静态路由,将预取完整路由(包括其所有数据)。对于动态路由,将预取到具有 loading.js 边界的最近路段的部分路由。

    ¥**null (default)**: Prefetch behavior depends on whether the route is static or dynamic. For static routes, the full route will be prefetched (including all its data). For dynamic routes, the partial route down to the nearest segment with a loading.js boundary will be prefetched.

  • true:将为静态和动态路由预取完整路由。

    ¥true: The full route will be prefetched for both static and dynamic routes.

  • false:进入视口和悬停时都不会发生预取。

    ¥false: Prefetching will never happen both on entering the viewport and on hover.

import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" prefetch={false}>
Dashboard
</Link>
)
}
import Link from 'next/link'

export default function Page() {
return (
<Link href="/dashboard" prefetch={false}>
Dashboard
</Link>
)
}

示例

¥Examples

链接到动态路由

¥Linking to Dynamic Routes

对于动态路由,使用模板字面量来创建链接的路径会很方便。

¥For dynamic routes, it can be handy to use template literals to create the link's path.

例如,你可以生成指向动态路由 app/blog/[slug]/page.js 的链接列表:

¥For example, you can generate a list of links to the dynamic route app/blog/[slug]/page.js:

import Link from 'next/link'

function Page({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}

如果子组件是封装 <a> 标签的自定义组件

¥If the child is a custom component that wraps an <a> tag

如果 Link 的子组件是封装 <a> 标签的自定义组件,则必须将 passHref 添加到 Link。如果你使用像 styled-components 这样的库,这是必要的。如果没有这个,<a> 标签将不会有 href 属性,这会损害你网站的可访问性并可能影响 SEO。如果你使用 ESLint,则有一个内置规则 next/link-passhref 可确保正确使用 passHref

¥If the child of Link is a custom component that wraps an <a> tag, you must add passHref to Link. This is necessary if you’re using libraries like styled-components. Without this, the <a> tag will not have the href attribute, which hurts your site's accessibility and might affect SEO. If you're using ESLint, there is a built-in rule next/link-passhref to ensure correct usage of passHref.

import Link from 'next/link'
import styled from 'styled-components'

// This creates a custom component that wraps an <a> tag
const RedLink = styled.a`
color: red;
`

function NavLink({ href, name }) {
return (
<Link href={href} passHref legacyBehavior>
<RedLink>{name}</RedLink>
</Link>
)
}

export default NavLink
  • 如果你使用 emotion 的 JSX pragma 功能 (@jsx jsx),则即使直接使用 <a> 标记,也必须使用 passHref

    ¥If you’re using emotion’s JSX pragma feature (@jsx jsx), you must use passHref even if you use an <a> tag directly.

  • 该组件应支持 onClick 属性才能正确触发导航

    ¥The component should support onClick property to trigger navigation correctly

如果子级是一个功能组件

¥If the child is a functional component

如果 Link 的子组件是功能组件,除了使用 passHreflegacyBehavior 之外,还必须将该组件封装在 React.forwardRef 中:

¥If the child of Link is a functional component, in addition to using passHref and legacyBehavior, you must wrap the component in React.forwardRef:

import Link from 'next/link'

// `onClick`, `href`, and `ref` need to be passed to the DOM element
// for proper handling
const MyButton = React.forwardRef(({ onClick, href }, ref) => {
return (
<a href={href} onClick={onClick} ref={ref}>
Click Me
</a>
)
})

function Home() {
return (
<Link href="/about" passHref legacyBehavior>
<MyButton />
</Link>
)
}

export default Home

替换 URL 而不是推送

¥Replace the URL instead of push

Link 组件的默认行为是将 push 新 URL 放入 history 堆栈中。你可以使用 replace 属性来防止添加新条目,如下例所示:

¥The default behavior of the Link component is to push a new URL into the history stack. You can use the replace prop to prevent adding a new entry, as in the following example:

<Link href="/about" replace>
About us
</Link>

禁用滚动到页面顶部

¥Disable scrolling to the top of the page

Link 的默认行为是滚动到页面顶部。当定义了哈希值时,它将滚动到特定的 id,就像普通的 <a> 标签一样。为了防止滚动到顶部/散列 scroll={false} 可以添加到 Link

¥The default behavior of Link is to scroll to the top of the page. When there is a hash defined it will scroll to the specific id, like a normal <a> tag. To prevent scrolling to the top / hash scroll={false} can be added to Link:

<Link href="/#hashid" scroll={false}>
Disables scrolling to the top
</Link>

中间件

¥Middleware

通常将 中间件 用于身份验证或涉及将用户重写到不同页面的其他目的。为了让 <Link /> 组件通过中间件重写正确地预取链接,你需要告诉 Next.js 要显示的 URL 和要预取的 URL。这是为了避免不必要的中间件获取来了解预取的正确路径。

¥It's common to use Middleware for authentication or other purposes that involve rewriting the user to a different page. In order for the <Link /> component to properly prefetch links with rewrites via Middleware, you need to tell Next.js both the URL to display and the URL to prefetch. This is required to avoid un-necessary fetches to middleware to know the correct route to prefetch.

例如,如果你想提供具有经过身份验证和访问者视图的 /dashboard 路由,你可以在中间件中添加类似于以下内容的内容,以将用户重定向到正确的页面:

¥For example, if you want to serve a /dashboard route that has authenticated and visitor views, you may add something similar to the following in your Middleware to redirect the user to the correct page:

export function middleware(req) {
const nextUrl = req.nextUrl
if (nextUrl.pathname === '/dashboard') {
if (req.cookies.authToken) {
return NextResponse.rewrite(new URL('/auth/dashboard', req.url))
} else {
return NextResponse.rewrite(new URL('/public/dashboard', req.url))
}
}
}

在这种情况下,你需要在 <Link /> 组件中使用以下代码:

¥In this case, you would want to use the following code in your <Link /> component:

import Link from 'next/link'
import useIsAuthed from './hooks/useIsAuthed'

export default function Page() {
const isAuthed = useIsAuthed()
const path = isAuthed ? '/auth/dashboard' : '/public/dashboard'
return (
<Link as="/dashboard" href={path}>
Dashboard
</Link>
)
}

版本历史

¥Version History

版本变化
v13.0.0不再需要子 <a> 标签。提供 codemod 来自动更新你的代码库。
v10.0.0指向动态路由的 href 属性会自动解析,不再需要 as 属性。
v8.0.0改进了预取性能。
v1.0.0next/link 推出。