Next.js中如何将[id]动态路由转换为slug格式自定义URL
Next.js 动态路由slug格式URL实现方案
你当前跳转异常的核心原因有两个:
- 路由文件结构和目标URL路径不匹配
- 动态路由参数名与
query传参的字段名不一致,Next.js无法识别动态路径参数,最终把参数拼到了URL查询串上
具体实现步骤
1. 调整文件系统路由结构
Next.js的路由路径和本地文件结构一一对应,你的目标URL格式为/slug/posttitle,因此需要按如下结构创建路由文件:
- 使用Pages Router:创建文件
pages/slug/[slug].js作为博客详情页 - 使用App Router:创建文件
app/slug/[slug]/page.js作为博客详情页
2. 修正Link组件代码
动态路径的参数名必须和query中传递的字段名完全一致,之前代码里动态参数写的是[slug],但query传的是title字段,Next.js无法匹配到动态参数就会出现你遇到的URL异常问题,正确代码如下:
<Link href={{ pathname: "/slug/[slug]", query: { slug: post.slug || post.title }, }} > {post.title} </Link>
注意:不建议直接用原始文章title作为URL参数,最好提前将title处理为符合URL规范的slug格式:转全小写、空格替换为短横线、移除特殊字符,例如标题
My First Post处理为my-first-post,避免中文、特殊符号导致URL解析异常。
3. 调整详情页参数获取逻辑
路由改完后,详情页获取参数的逻辑也要对应调整:
- Pages Router 示例:
// pages/slug/[slug].js export async function getServerSideProps(context) { // 从query中获取slug参数查询对应文章 const postSlug = context.query.slug const post = await fetchPostBySlug(postSlug) return { props: { post } } } export default function PostDetail({ post }) { return <div>{post.title}</div> }
- App Router 示例:
// app/slug/[slug]/page.js async function fetchPostBySlug(slug) { // 文章查询逻辑 return {} } export default async function PostDetail({ params }) { const post = await fetchPostBySlug(params.slug) return <div>{post.title}</div> }
无/slug前缀的实现补充
如果你不需要/slug前缀,想要最终URL为http://localhost:3001/posttitle格式,只需要做两个调整:
- 将路由文件放在根路径,命名为
pages/[slug].js(Pages Router)或app/[slug]/page.js(App Router) - 将Link组件的pathname改为
/[slug]即可,query字段依然保持slug和动态参数名一致
内容的提问来源于stack exchange,提问作者amit
相关产品推荐
相关产品推荐

