硅基同事埋的坑,我用2小时才填平:Nuxt 4 路由踩坑:可选参数 [[id]] 与 [id] 的区别

个人网站

在开发博客系统时,遇到了一个路由不生效的问题:/section 可以访问,但 /section/id 却始终无法匹配。折腾了一番后发现是 Nuxt 文件路由的可选参数语法理解有误。

问题背景

需求很简单:

  • /blog → 显示博客列表,默认选中第一篇文章
  • /blog/kubernetes-1-32-release → 显示博客列表,选中指定文章

最初创建了两个路由文件:

ini 复制代码
pages/
├── [section].vue        # 匹配 /blog
└── [section]/
    └── [id].vue         # 匹配 /blog/xxx

结果:/blog 正常,/blog/kubernetes-1-32-release 却始终匹配不上。

问题原因

最初采用了两个独立文件的方式:

ini 复制代码
pages/
├── [section].vue        # 匹配 /blog
└── [section]/
    └── [id].vue         # 匹配 /blog/xxx

这种结构看似合理,实则存在多个问题:

  1. 代码重复:两个文件 95% 代码相同,维护成本高
  2. 状态同步:需要额外处理跨页面状态共享
  3. 路由匹配 :某些情况下 Nuxt 无法正确区分两个路由,导致 /blog/xxx 匹配失败

解决方案

Nuxt 提供了可选路由参数 语法 ------ 双括号 [[param]],用一个文件同时处理两种情况:

lua 复制代码
pages/
└── [section]/
    └── [[id]].vue    # 同时匹配 /blog 和 /blog/xxx

核心区别

语法 含义 匹配示例
[id] 必需参数 /blog/abc ✅ / /blog
[[id]] 可选参数 /blog/abc ✅ / /blog

[[id]] 是 Nuxt/Vue Router 的特殊语法,表示该参数可以存在也可以不存在

实现方案

合并后的 [[id]].vue

vue 复制代码
<script setup>
const route = useRoute()
const section = route.params.section
const articleId = route.params.id  // 可能为 undefined

// 有 id 用 id,没有则用 firstArticleId
const activeArticleId = ref(articleId || firstArticleId)

// 监听路由变化(SPA 导航时更新)
watch(() => route.params.id, (newId) => {
  if (newId) activeArticleId.value = newId
})

// 点击文章时更新 URL
const handleSelectArticle = (id) => {
  activeArticleId.value = id
  navigateTo(`/${section}/${id}`, { replace: true })
}
</script>

关键点

  1. route.params.id 可能为 undefined:需要提供默认值
  2. 添加路由监听:SPA 内导航时 URL 变化不会重新执行 setup,需要 watch
  3. navigateTo 更新 URL:选中文章时同步 URL,支持分享和书签

调试技巧

在排查过程中,发现 Nuxt 4 的 console.log 在 SSR 阶段可能被过滤。一个实用的做法是在 composable 中添加显眼前缀:

ts 复制代码
export function useContentArticles(section: string) {
  console.log('>>> [useContentArticles] section:', section)
  console.log('>>> [useContentArticles] cache keys:', Object.keys(sectionDataCache))
  // ...
}

终端输出:

less 复制代码
>>> [useContentArticles] section: blog
>>> [useContentArticles] cache keys: [ 'blog', 'interview', 'nuxt4' ]

总结

场景 推荐方案
单一页面 + 可选子路径 [[id]].vue
完全不同的两个页面 分开两个文件
参数必需 [id].vue

可选参数 [[param]] 是 Nuxt 文件路由的利器,用好了可以大幅减少代码重复。但要注意处理 undefined 的情况和路由变化的监听。

延伸阅读

nuxt4完整系列,持续更新中...

内容有帮助?点赞、收藏、关注三连!评论区等你 💪

相关推荐
子兮曰19 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰19 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万19 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝19 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋20 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁20 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端