【欢迎订阅我的Nextjs 15专栏,有你需要的入门必备常识】
上篇我们了解如何初始化一个Nextjs项目,如何定义路由【可移步初始Nextjs路由】
本篇讲讲如何在Nextjs实现导航
"导航",就是使用JavaScript进行页面切换,通常比浏览器默认重新加载更快。因为只会加载必要组件,不会全部加载整个页面,类似“懒加载”的功能。
在Next.js中,有4种方式实现路由导航:
- 使用
<Link>组件 - 使用
useRouterHook(客户端组件) - 使用
redirect函数(服务端组件) - 使用浏览器原生 History API
<Link> 组件:推荐的导航方式
Next.js 的 <Link> 组件是基于原生 HTML <a> 标签扩展而来的,它不仅能实现页面跳转,还能进行预获取(prefetching),这可是 Next.js 推荐的路由导航方式。
基础用法
先来看最简单的用法。比如你想从当前页面跳转到“Dashboard”页面,代码可以这样写:
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
动态路由的渲染
有时候,页面的链接是动态生成的,比如一个博客列表,每篇文章都有自己的链接。这时候,<Link> 组件也能轻松搞定:
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()。比如在导航栏中,给当前激活的链接加上特殊样式:
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Navigation({ navLinks }) {
const pathname = usePathname()
return (
<>
{navLinks.map((link) => {
const isActive = pathname === link.href
return (
<Link
className={isActive ? 'text-blue' : 'text-black'}
href={link.href}
key={link.name}
>
{link.name}
</Link>
)
})}
</>
)
}
跳转行为的设置
默认情况下,App Router 会在跳转到新路由时滚动到页面顶部,或者在前进后退时保持之前的滚动位置。如果你不想这样,可以在 <Link> 组件中加上 scroll={false} 属性,或者在使用 router.push 和 router.replace 时设置 scroll: false:
// 使用 <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.js 提供的一个 Hook,专门用来在客户端组件中更改路由。用起来也很简单,比如你想通过按钮点击跳转到“Dashboard”页面:
'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 只能在客户端组件中使用哦,记得在文件顶部加上 'use client' 声明。
redirect 函数:服务端组件的跳转
如果你在服务端组件中需要进行路由跳转,可以直接使用 redirect 函数。比如在获取数据失败时,跳转到登录页面:
import { redirect } from 'next/navigation'
async function fetchTeam(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
History API:原生的路由控制
除了 Next.js 自带的路由方法,你还可以使用浏览器原生的 window.history.pushState 和 window.history.replaceState 方法来更新浏览器的历史记录。
比如,你想对一个产品列表进行排序,可以用 pushState:
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}
return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
如果想切换应用的语言设置,可以用 replaceState,这样用户就无法通过后退按钮回到之前的语言设置:
'use client'
import { usePathname } from 'next/navigation'
export default function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale) {
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}
总结
通过这几种方式,Next.js 提供了灵活的路由导航解决方案,无论是客户端还是服务端,都能轻松实现页面跳转。虽然我们今天只是简单介绍了这些方法,但它们已经足够你在写 Demo 的时候使用了。后续我们会详细讲解更多相关概念,比如客户端组件和服务端组件的区别,以及各种 Hooks 和函数的深入用法。
参考链接