Next.js动态路由URL如何在名称间添加短横线(-)替代编码字符
动态路由URL短横线格式化实现方案
你遇到的%20、%E2等URL编码问题,是因为传入路由的原始参数包含空格、中文、特殊符号这类URL非法字符,浏览器会自动对这类字符做编码处理。只要将传入的参数转换为符合规范的短横线分隔小写格式(俗称slug)即可解决,具体实现步骤如下:
1. 封装slug转换工具函数
首先实现一个通用格式转换方法,将任意字符串处理为短横线分隔的标准格式:
// utils/slugify.ts export function slugify(text: string): string { return text .toString() .toLowerCase() .trim() // 替换空格、下划线为短横线 .replace(/[\s_]+/g, '-') // 移除非字母数字、短横线、中文的无效字符 .replace(/[^\w\u4e00-\u9fa5-]+/g, '') // 合并连续的多个短横线为单个 .replace(/--+/g, '-') // 移除首尾多余的短横线 .replace(/^-+/, '') .replace(/-+$/, '') }
如果需要把中文也转为拼音格式的slug,可以引入pinyin等第三方拼音转换库,在转换逻辑中先把中文转成拼音再做后续处理即可。
2. 路由跳转前先转换参数
不要直接把原始文章名称传入路由,跳转前先调用slugify方法处理参数:
- 使用
Link组件跳转示例:
import Link from 'next/link' import { slugify } from '@/utils/slugify' // 示例文章数据 const post = { id: 68041539, title: "Using dash in the dynamic route name" } // 跳转写法 <Link href={`/post/${slugify(post.title)}`}> {post.title} </Link>
- 编程式跳转示例:
import { useRouter } from 'next/router' import { slugify } from '@/utils/slugify' const router = useRouter() const jumpToPost = (title: string) => { router.push(`/post/${slugify(title)}`) }
3. 动态路由页面匹配数据
在pages/post/[postname].tsx中拿到的postname已经是标准slug格式,建议你存储文章时提前把生成好的slug存入数据库,直接用slug作为查询条件匹配对应文章即可:
// pages/post/[postname].tsx import { GetStaticProps, GetStaticPaths } from 'next' import { getPostBySlug, getAllPosts } from '@/lib/post' export const getStaticPaths: GetStaticPaths = async () => { const paths = getAllPosts().map(post => ({ params: { postname: post.slug } })) return { paths, fallback: false } } export const getStaticProps: GetStaticProps = async ({ params }) => { const post = await getPostBySlug(params.postname as string) return { props: { post } } }
优化建议
如果允许重复标题,可以调整URL为/post/[文章ID]/[slug]的结构:
- 既可以保证URL全局唯一,避免重复slug匹配错误
- 查询时直接用ID检索即可,不需要完全依赖slug匹配,容错性更高
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

