在上一章中,您创建了仪表板布局和页面。现在,让我们添加一些链接,以便用户能够在仪表板路由之间进行导航。
本章内容
我们将涵盖以下主题:
- 如何使用
next/link
组件。 - 如何使用
usePathname()
钩子显示活动链接。 - 了解 Next.js 中的导航工作原理。
为什么要优化导航?
通常,您会使用 <a>
HTML 元素在页面之间链接。目前,侧边栏链接使用 <a>
元素,但请注意,当您在浏览器中导航到主页、发票页面和客户页面时会发生什么。
发现了吗? 每次页面导航时,整个页面都会刷新!
<Link> 组件
在 Next.js 中,您可以使用 <Link />
组件在应用程序的页面之间进行链接。<Link>
允许您使用 JavaScript 进行客户端导航(client-side navigation)。
要使用 <Link />
组件,请打开 /app/ui/dashboard/nav-links.tsx
文件,并从 next/link(next/link) 中导入 Link
组件。然后,将 <a>
标签替换为 <Link>
:
// /app/ui/dashboard/nav-links.tsx 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) 不同,浏览器会在初次加载时加载您所有的应用程序代码。
按路由拆分代码意味着页面是独立的。如果某个页面发生错误,应用程序的其他部分仍然可以正常工作。
此外,在生产环境中,当 组件出现在浏览器视口中时,Next.js 会在后台自动预取链接路由的代码。当用户点击链接时,目标页面的代码已经在后台加载完毕,这使得页面切换几乎是即时的!
了解更多 导航工作原理(how navigation works)。
现在是测验时间!
在生产环境中,当 <Link>
组件出现在浏览器视口中时,Next.js 会做什么?
A. 下载额外的 CSS B. 预加载图片 C. 预取链接路由的代码 D. 启用链接路由的懒加载
Pattern: 显示活动链接
一个常见的 UI 模式是显示一个活动链接,以指示用户当前所在的页面。要做到这一点,您需要从 URL 中获取用户的当前路径。Next.js 提供了一个名为 usePathname()
的钩子,您可以使用它来检查路径并实现此模式。
由于 usePathname()
是一个钩子,您需要将 nav-links.tsx
转换为客户端组件。在文件顶部添加 React 的 "use client"
指令,然后从 next/navigation
中导入 usePathname()
:
// /app/ui/dashboard/nav-links.tsx 'use client'; import { UserGroupIcon, HomeIcon, InboxIcon } from '@heroicons/react/24/outline'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; // ...
接下来,在 <NavLinks />
组件中,将路径分配给名为 pathname
的变量:
// /app/ui/dashboard/nav-links.tsx export default function NavLinks() { const pathname = usePathname(); // ... }
您可以使用在 CSS 样式 一章中介绍的 clsx
库来有条件地应用类名,以便当链接处于活动状态时显示蓝色文本和浅蓝色背景。当 link.href
与 pathname
匹配时,该链接应显示为蓝色文本和浅蓝色背景。
以下是 nav-links.tsx
的最终代码:
// /app/ui/dashboard/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> ); })} </> ); }
保存并检查您的本地服务器。您现在应该能看到当前激活的链接会以蓝色
突出显示。