<Link> 3个月前

编程语言
762
<Link>

<Link> 是一个扩展了 HTML <a> 元素的 React 组件,提供了预加载和客户端路由导航功能。它是 Next.js 中导航不同路由的主要方式。

// app/page.tsx
import Link from 'next/link';

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

Props

以下是 Link 组件可用的 props 的总结:

Prop 示例 类型 必需
href href="/dashboard" 字符串或对象
replace replace={false} 布尔值
scroll scroll={false} 布尔值
prefetch prefetch={false} 布尔值或 null

注意<a> 标签的属性如 classNametarget="_blank" 可以作为 props 添加到 <Link> 中,并传递给底层的 <a> 元素。

href (必需)

导航到的路径或 URL。

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

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

// 导航到 /about?name=test
<Link href={{
  pathname: '/about',
  query: { name: 'test' },
}}>
  About
</Link>

replace

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

import Link from 'next/link';

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

scroll

默认值为 true <Link> 的默认行为是在导航到新路由时滚动到页面顶部,或者在向前或向后导航时保持滚动位置。当设置为 false 时,next/link 在导航后不会滚动到页面顶部。

import Link from 'next/link';

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

注意

  • 如果在导航后页面不可见,Next.js 会滚动到页面顶部。

prefetch

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

  • null(默认):预加载行为取决于路由是静态还是动态的。对于静态路由,整个路由将被预加载(包括所有数据)。对于动态路由,将预加载直到最近的带有loading.js边界的部分路由。
  • true:静态和动态路由都会进行完整的预加载。
  • false:无论是进入视口还是悬停时,都不会进行预加载。
import Link from 'next/link';

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

示例

链接到动态路由

对于动态路由,使用模板字符串创建链接路径非常方便。

例如,您可以生成指向动态路由 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> 标签的自定义组件

如果 Link 的子组件是一个包裹 <a> 标签的自定义组件,您必须将 passHref 添加到 Link 中。如果您使用类似 styled-components 的库,这是必需的。否则,<a> 标签将不会有 href 属性,这会影响网站的可访问性并可能影响 SEO。如果您使用 ESLint,内置规则 next/link-passhref 可以确保正确使用 passHref

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

// 创建一个包裹 <a> 标签的自定义组件
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
  • 组件应支持 onClick 属性,以正确触发导航。

如果子组件是函数式组件

如果 Link 的子组件是函数式组件,除了使用 passHreflegacyBehavior,还必须将组件包装在 React.forwardRef 中:

import Link from 'next/link';

// `onClick`、`href` 和 `ref` 需要传递给 DOM 元素
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 而不是推送

Link 组件的默认行为是将新的 URL pushhistory 堆栈中。您可以使用 replace prop 来防止添加新条目,如下例所示:

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

禁用滚动到页面顶部

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

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

中间件

通常使用中间件进行身份验证或其他涉及将用户重写到不同页面的操作。为了使 <Link /> 组件正确预加载通过中间件重写的链接,您需要告诉 Next.js 要显示的 URL 和要预加载的 URL。这对于避免中间件不必要的请求非常重要,以知道正确的路由进行预加载。

例如,如果您想为 /dashboard 路由提供已验证和访客视图,您可以在中间件中添加类似以下内容,将用户重定向到正确的页面:

// middleware.js
import { NextResponse } from 'next/server';

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 /> 组件中使用以下代码:

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 (
    // 使用 as 和 href 来分别指定要显示的 URL 和要预加载的实际 URL
    <Link as="/dashboard" href={path}>
      Dashboard
    </Link>
  );
}

在上述代码中,as prop 指定用户在浏览器中看到的 URL,而 href prop 指定实际被加载的 URL。通过这种方式,Next.js 可以根据中间件的重写逻辑正确地预加载相关内容,从而提高性能并确保用户体验的一致性。

这种模式特别适用于具有多个访问级别的页面或在不同条件下需要重写 URL 的场景。

版本

版本号 变更
v13.0.0 不再需要子 <a> 标签。提供了一个 codemod 来自动更新代码库。
v10.0.0 指向动态路由的 href 属性会自动解析,不再需要 as 属性。
v8.0.0 改进了预加载性能。
v1.0.0 next/link 被引入。
image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2222878
累计阅读

热门教程文档

Golang
23小节
C
14小节
PHP
52小节
QT
33小节
Swift
54小节