课程/前端到全栈

动态路由:一个模板,无数个网址

上一篇结尾留了个麻烦:想做博客,文章有几十上百篇,按前几篇的玩法,得建几十个文件夹、写几十个 page.tsx——想想就离谱。

而且这些页面除了文章内容不同,长得一模一样:都是"标题 + 正文"的排版。为几乎相同的页面复制粘贴几十次,程序员最恨干这个。

Next.js 的解法,就是本篇的主角:动态路由——只建一个模板页面,吃掉无数个网址。

用旅店房间理解动态路由

先回忆静态路由:一个文件夹对一个网址,about 文件夹就是 /about——像自家门牌,一一对应。

动态路由更像旅店的房间号:

  • 旅店不会给每间房单独起名字,而是挂个牌子:"X 号房"
  • 不管住进来的是张三还是李四,房间的格局都一样,只是"住客"不同
  • 服务台看牌子就知道:"哦,X 是变量,谁住都行"

Next.js 里,这个"X 号房牌子"就是带方括号的文件夹名:

app/blog/[slug]/page.tsx

[slug] 的意思是:/blog/ 后面不管跟什么,都进这个 page.tsx 于是:

  • localhost:3000/blog/hello → 进模板,slug = "hello"
  • localhost:3000/blog/my-first-post → 进模板,slug = "my-first-post"
  • localhost:3000/blog/随便什么 → 还是进模板,slug = "随便什么"

网址里那段变化的值(hello、my-first-post),会像"住客登记"一样被记下来,交给页面使用。一个模板,无数个网址——博客、商品页、用户主页,全互联网都是这么干的。

slug 这个词是圈里的习惯叫法,指"网址里那段给人看的标识"。你可以把它理解成"这篇文章的网址小名"。方括号里写别的名字也行(比如 [id]),slug 只是约定俗成。

实战:建一个"万能文章页"

目标:做一个博客详情页模板,把网址里的 slug 直接显示在页面上,证明"它真的接到了网址里的值"。

对 Agent 说:

帮我建一个动态路由页面,要求:

  • 路径是 app/blog/[slug]/page.tsx
  • 页面功能:显示一行大标题"文章详情页",下面一行显示"当前文章的 slug 是:xxx",xxx 要替换成网址里的真实 slug
  • 用 Next.js App Router 动态路由的方式实现

建好后,文件树里会多出:

app/
└── blog/
    └── [slug]/          ← 方括号文件夹,"X 号房"
        └── page.tsx     ← 万能模板

验收:连换三个网址

这一篇的验收特别有意思——一个页面,当成好几个页面来测。项目保持运行,依次访问:

localhost:3000/blog/hello
localhost:3000/blog/ai-is-cool
localhost:3000/blog/123

每次都看页面上那行字:"当前文章的 slug 是:xxx"里的 xxx,必须跟着网址变。

  • 访问 /blog/hello 显示 hello ✓
  • 访问 /blog/ai-is-cool 显示 ai-is-cool ✓
  • 访问 /blog/123 显示 123 ✓

三次都对,说明动态路由真的通了:同一个模板,接住了三个不同的网址,还准确取出了每段值。

再补一刀验证:访问 localhost:3000/blog(不带 slug)——应该 404。这是对的:/blog 这个门牌号还没人占(马上就会占了)。

看一眼:slug 是怎么进页面的

打开 app/blog/[slug]/page.tsx,重点看一行:

export default function BlogPage({ params }: { params: { slug: string } }) {
  return (
    <main>
      <h1>文章详情页</h1>
      <p>当前文章的 slug 是:{params.slug}</p>
    </main>
  );
}

不用懂那些弯弯绕绕的符号,只抓住一条线索:

Next.js 把网址里那段值装进 params,页面用 params.slug 取出来。

就像住客登记后,前台把房卡(params)递给你,你刷卡(.slug)进门。页面上那个 {params.slug} 的位置,显示的就是网址里的值。

现在还只是"把 slug 显示出来"凑个热闹。等第 7 章学了数据库,这个位置就会变成真正的文章内容——按 slug 去库里查文章。模板不用改,只是换了个数据源。

顺手升级:给博客补一个列表页

模板有了,再加一个 /blog 列表页,把上一篇的 <Link> 用起来。对 Agent 说:

再建一个 /blog 列表页,页面上用 Link 列出三篇假文章的入口:

  • "我的第一篇文章"指向 /blog/hello
  • "学习心得"指向 /blog/ai-is-cool
  • "随便写写"指向 /blog/123

完成后访问 localhost:3000/blog——这次不 404 了,是一个列表页。点任意一条,秒切进详情页,slug 还显示得对。

到这里,博客的骨架已经闭环:列表页(静态路由)→ 详情页(动态路由)→ 点链接来回跳(<Link>)。三篇的知识,全用上了。

新手常问

Q:方括号文件夹建起来好别扭,能手动建吗?

能,和普通文件夹一样建,只是名字带 [ ]。不过照例——让 Agent 建最省心。

Q:slug 里能有中文吗?比如 /blog/我的文章?

能访问,但网址里的中文会被浏览器转成一长串 %E6%88%91... 的编码,又丑又长。圈里的习惯是 slug 只用英文、数字、连字符,中文标题留给页面内容。(这也是本教程网站自己的做法:网址全英文,标题全中文。)

Q:动态路由能套娃吗?比如 /blog/2026/08/my-post?

能,每层都可以是动态的([year]/[month]/[slug]),甚至还有一口吃掉任意多层的"全捕获"写法(本教程网站的文档页就是用它做的)。入门阶段先把单层用熟。

Q:如果两篇"文章"想用不同的排版怎么办?

动态路由的前提是"同一类页面共用一副模板"。真有长得不一样的页面,那就不是同一类,老老实实分开建文件夹。

本篇小结

  • 动态路由 = 方括号文件夹(如 [slug]),一个模板接住无数个网址
  • 网址里变化的值通过 params.slug 传给页面,像前台递房卡
  • 验收动态路由的标准动作:连换几个网址,看页面内容跟着变
  • 列表页(静态)+ 详情页(动态)+ <Link> 串联 = 博客的最小闭环
  • 现在的"文章"还是假的(只显示 slug),真的内容要等第 7 章接上数据库

路由的三板斧——静态路由、<Link> 跳转、动态路由——到这里全部出齐。下一篇是本章的收官实战:把四篇学到的东西攒成一个完整的多页面小站,有首页、有导航、有博客列表和详情,能跑能看能点。

💬 评论(0)

请登录后参与评论

加载中...