news 2026/8/25 17:19:12

Next.js 的客户端页面路由详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Next.js 的客户端页面路由详解

文章目录

    • 1. 路由的基本概念
    • 2. 客户端路由的核心
      • (1) `useRouter`
      • (2) `<Link />` 组件
      • (3) `redirect()`
    • 3. 动态路由与客户端获取参数
    • 4. 客户端路由和服务端路由的区别
    • 5. 路由案例
      • 1. `app/layout.tsx` (全局布局)
      • 2. `app/components/NavBar.tsx` (导航栏)
      • 3. `app/page.tsx` (首页)
      • 4. `app/blog/[id]/page.tsx` (详情页)
      • 效果

1. 路由的基本概念

Next.js 15(App Router 模式)中,路由主要依赖文件系统路由(File-system routing),所有页面都放在app/目录下:

app/ ├── page.tsx // 对应 "/" ├── about/ │ └── page.tsx // 对应 "/about" └── blog/ └── [id]/ └── page.tsx // 动态路由 "/blog/123"
  • 服务端渲染 (SSR):页面初次加载时由服务器返回 HTML。
  • 客户端路由 (CSR):在页面之间跳转时,Next.js使用客户端路由器(基于 React Router-like 机制)来实现无刷新切换

2. 客户端路由的核心

客户端路由由next/navigation提供,主要用到两个Hook / API

(1)useRouter

用于编程式导航,和 React Router 的useNavigate类似。

"use client";import{useRouter}from"next/navigation";exportdefaultfunctionHome(){constrouter=useRouter();return<button onClick={()=>router.push("/about")}>去 About 页面</button>;}
  • router.push("/path"):跳转到某个页面,保留历史记录。
  • router.replace("/path"):跳转但不保留历史记录。
  • router.back():回退。

(2)<Link />组件

推荐使用<Link>来实现预加载和无刷新跳转

importLinkfrom"next/link";exportdefaultfunctionNavBar(){return(<nav><Link href="/">首页</Link><Link href="/about">关于我们</Link></nav>);}
  • <Link>默认会预加载目标页面的代码,提高切换速度。
  • 只有当目标在视口中可见时才会自动预加载。

(3)redirect()

用于服务端或客户端强制重定向。

import{redirect}from"next/navigation";exportdefaultfunctionPage(){constisLogin=false;if(!isLogin){redirect("/login");}return<div>已登录</div>;}

3. 动态路由与客户端获取参数

动态路由文件夹[id]会捕获 URL 中的参数。

文件夹嵌套结构:app/blog/[id]/page.tsx如下:

app/ ├── blog/ │ └── [id]/ │ └── page.tsx // 动态路由 "/blog/123"

组件获取如下:

// app/blog/[id]/page.tsx"use client";import{useParams}from"next/navigation";exportdefaultfunctionBlogPage(){constparams=useParams();// { id: "123" }return<h1>文章ID:{params.id}</h1>;}// 如果是 服务端渲染,直接通过 `params` 获取:exportdefaultfunctionBlogPage({params}:{params:{id:string}}){return<h1>文章ID:{params.id}</h1>;}

上面这种方式只能获取一层动态路由参数,不能获取嵌套路由参数(例如/blog/123/comment/456就报错了)。

路由结构改用[...id]如下:

app/ ├── blog/ │ └── [...id]/ │ └── page.tsx // 动态路由 "/blog/123/comment/456"

这样就可以获取到多层动态路由参数了。

还有一种情况我们想让这个路由参数是可选的,有没有都可以,那么在外层再包裹一层中括号变成了[[...id]],如下:

app/ ├── blog/ │ └── [[...id]]/ │ └── page.tsx // 动态路由 "/blog/123/comment/456"

动态路由总结:

  • [id]:只能获取一层路由参数,例如/blog/123
  • [...id]:可以获取多层路由参数,例如/blog/123/comment/456
  • [[...id]]:路由参数是可选的,有没有都可以,例如/blog/123/blog/123/comment/456

4. 客户端路由和服务端路由的区别

特性服务端渲染 (SSR)客户端路由 (CSR)
初次加载服务器生成 HTML前端只加载入口 HTML
跳转整页刷新 / SSR无刷新跳转,速度快
数据获取通过fetch()/server actionsuseEffect/ SWR / TanStack Query
SEO较弱(需 SSR/ISR 支持)

Next.js 的优势就是两者结合—— 初次请求走 SSR,后续页面切换走 CSR。

5. 路由案例

整个案例包含:

  • 首页/:有一个跳转按钮,去详情页
  • 详情页/blog/[id]:显示文章 ID
  • 导航栏组件:全局无刷新跳转

项目结构

app/ ├── layout.tsx ├── page.tsx // 首页 ├── blog/ │ └── [id]/ │ └── page.tsx // 动态详情页 └── components/ └── NavBar.tsx // 导航栏

1.app/layout.tsx(全局布局)

import"./globals.css";importNavBarfrom"./components/NavBar";exportdefaultfunctionRootLayout({children}:{children:React.ReactNode}){return(<html lang="en"><body><NavBar/><main>{children}</main></body></html>);}

2.app/components/NavBar.tsx(导航栏)

"use client";importLinkfrom"next/link";exportdefaultfunctionNavBar(){return(<nav style={{display:"flex",gap:"20px",marginBottom:"20px"}}><Link href="/">首页</Link><Link href="/blog/123">文章123</Link><Link href="/blog/456">文章456</Link></nav>);}

3.app/page.tsx(首页)

"use client";import{useRouter}from"next/navigation";exportdefaultfunctionHomePage(){constrouter=useRouter();return(<div><h1>首页</h1><button onClick={()=>router.push("/blog/999")}style={{marginTop:"20px"}}>去文章999</button></div>);}

4.app/blog/[id]/page.tsx(详情页)

"use client";import{useParams,useRouter}from"next/navigation";exportdefaultfunctionBlogDetail(){constparams=useParams();// { id: "123" }constrouter=useRouter();return(<div><h1>文章详情</h1><p>当前文章ID:{params.id}</p><button onClick={()=>router.back()}>返回上一页</button></div>);}

效果

  1. 打开/→ 首页

    • 可以点击「去文章 999」按钮 → 跳转/blog/999
  2. 在导航栏点击/blog/123/blog/456→ 跳转不同文章详情

  3. 在详情页点「返回上一页」 → 回到首页


🚀 感谢阅读!想了解更多?

📖 我的博客网站 | 记录思考,分享干货
🏡 我的个人主页 | 关于我、开源项目


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 17:15:57

Redis五大核心数据结构详解:从缓存到数据结构服务器的进阶指南

1. 从“键值对”到“数据结构服务器”&#xff1a;理解Redis的核心定位很多刚接触Redis的朋友&#xff0c;第一印象往往是“一个很快的缓存”。这没错&#xff0c;但只说对了一半。如果仅仅把它当作一个带过期时间的HashMap来用&#xff0c;那真是“杀鸡用牛刀”&#xff0c;浪…

作者头像 李华
网站建设 2026/8/25 17:07:03

从通用模型到专业定制:AI应用从“龙虾”到“爱马仕”的范式演进

1. 从“龙虾”到“爱马仕”&#xff1a;AI圈术语迭代背后的逻辑最近在AI圈子里&#xff0c;如果你还张口闭口“龙虾”&#xff0c;可能已经有点跟不上趟了。一股新的“养马”风潮正在悄然兴起&#xff0c;从技术讨论区到项目文档&#xff0c;再到一些前沿的论文解读&#xff0c…

作者头像 李华
网站建设 2026/8/25 17:06:06

从 JEPA 演进到 WAM:LeWorldModel 与 Fast-WAM 的一条连续技术脉络

0. 简介 2026 年 3 月到 4 月&#xff0c;世界模型方向连续出现了两组放在一起看才真正有意思的信号。第一组来自 JEPA 路线本身&#xff1a;从 V-JEPA 2、LeJEPA、Causal-JEPA、LeWorldModel、V-JEPA 2.1 到 ThinkJEPA&#xff0c;这条原本常被当作“抽象表征学习方法”的路线…

作者头像 李华
网站建设 2026/8/25 17:06:00

企业级AI Agent标准测评:从可靠性到场景适配的硬核评估指南

1. 项目概述&#xff1a;一场关于“标准”的硬核追问最近在AI圈里&#xff0c;尤其是企业服务和技术决策者之间&#xff0c;一个话题的热度居高不下&#xff1a;企业级AI Agent的标准&#xff0c;到底谁说了算&#xff1f;是那些发布宏伟蓝图的科技巨头&#xff0c;是开源社区里…

作者头像 李华
网站建设 2026/8/25 17:04:42

CLI命令行界面:从基础原理到高效开发与运维实践

1. 从“图形化”到“命令行”&#xff1a;为什么说CLI是效率的终极形态如果你还在用鼠标点点点&#xff0c;在层层叠叠的菜单里寻找一个功能&#xff0c;或者被某个软件突然改版的界面搞得晕头转向&#xff0c;那你可能真的需要停下来&#xff0c;重新认识一下你面前的电脑了。…

作者头像 李华
网站建设 2026/8/25 17:00:16

解决Redis局域网内不能访问的问题(Windows/Linux/虚拟机)

最近在使用Redis&#xff0c;出现局域网 不能访问的问题&#xff08;Windows/Linux&#xff09;&#xff0c;解决办法如下&#xff1a;Windows环境&#xff1a;1.关闭bind 127.0.0.1或者&#xff0c;改为0.0.0.02.检查redis的配置文件&#xff0c;是否开启的保护模式&#xff1…

作者头像 李华