
前阵子用 Claude Code 做博客CMS接到一个看似不起眼的需求文章详情页动态路由/article/:id。当时我觉得这东西太常规了直接在提示词里写了一句“开发一个文章详情页”结果 Claude Code 生成的代码给我上了一课——没有上下文再强的模型也只会给你一套“标准答案”而不是“正确答案”。后来我把提示词重构成结构化规格书配合两轮追问才真正把这页面做成可以上线的状态。这个案例特别适合拿出来复盘因为动态路由详情页看似简单实际是前端开发里最容易翻车的场景之一路由参数怎么取、组件复用时怎么触发更新、异步请求并发怎么处理、返回列表页时状态怎么保留每一个环节都可能出问题。而这些问题恰恰是 Claude Code 这类 AI 编程工具最需要你通过提示词去表达清楚的地方。这篇文章我会把完整的提示词案例、背后的设计思路、实际踩过的坑都摊开讲一遍希望能给你一些可以直接抄作业的东西。1. 需求拆解为什么动态路由详情页是提示词翻车重灾区1.1 动态路由详情页的隐藏复杂度先说清楚动态路由是什么。像/article/:id这种路径id是变量同一个路由文件承载的是不同数据。前端拿到这个id调接口拿数据再渲染页面。听起来简单但实际项目里它有四层隐藏复杂度。第一层是参数获取与校验。Vue Router 里要用route.params.idReact Router 里要用useParams()取出来的值还需要判断是否合法不合法就要走 404 或者重定向。很多 AI 生成代码会忽略这一步直接把id塞进接口请求等后端报错才反应过来说参数有问题。第二层是组件复用。从/article/1跳到/article/2路由组件实例是复用的不会重新走 mounted如果没有监听route.params的变化页面会一直显示第一篇文章。这也是 Claude Code 这类工具很容易漏的地方因为单文件生成时它没有全局视角。第三层是异步竞态。用户快速切换文章时前一个请求可能比后一个请求更慢返回如果不做竞态处理页面会被旧数据覆盖。这个细节很多初级开发者都意识不到模型更不会主动给你写除非你在提示词里明确要求。第四层是页面状态留存。从列表页进详情页再返回列表页时页码和滚动位置应该保留。这涉及到列表页的缓存策略、keep-alive的配置、路由的 scroll behavior是一整套跨页面的联动逻辑。你把这些复杂度列出来就会发现一个事实详情页不是一个页面而是一套完整的状态链路。普通一句话提示词根本表达不了这个链路所以 Claude Code 大概率只会给你一个“能跑但很脆”的 demo数据能显示、样式还行但一刷新、一快速切换、一返回全是问题。1.2 普通提示词为什么写不出合格详情页我复盘过自己翻车的那次提示词就一句话“帮我写一个文章详情页路径是 /article/:id用 Vue3 TS。”Claude Code 生成的代码从语法上讲没毛病但离可用差得远路由配了组件写了接口也调了可没有加载状态、没有错误处理、没有参数变化监听、没有竞态处理、没有 SEO 基础标签更别提返回列表页的状态恢复了。问题不在模型能力而在提示词的“信息密度”。Claude Code 本质上是根据你给的上下文去预测最合理的代码它不知道你的项目里有没有统一的请求封装、不知道设计师要求的骨架屏长什么样、不知道你要不要缓存、不知道路由是怎么组织的。它会默认选一个“最大概率正确”的方案而这个方案往往是通用得不能再通用的实现。我用一个对比来说明维度一句话提示词结构化提示词角色未指定指定资深前端工程师角色技术栈只说 Vue3 TS明确到 Vue Router 4、Pinia、Vite、接口封装方式功能清单未给逐条列出标题、正文、评论、推荐、标签等模块边界条件未提明确要求处理 loading、error、404、竞态、参数变化文件结构交给模型随意发挥明确组件目录、文件职责、路由注册方式验证标准无提供自检点让 AI 输出前检查同样的需求信息密度不同产出完全不是一个量级。所以我把“给 Claude Code 写提示词”这件事重新定义成写一份领域内的技术规格书而不是描述性的需求文。2. 提示词结构化设计把需求变成 AI 能执行的“规格书”2.1 提示词的六大关键要素我把写提示词比喻成给一个新同事交代任务。如果你只说“把那个详情页做了”他大概率会按自己的经验去猜技术栈可能猜错接口路径可能猜错文件放哪也可能猜错。但如果你把角色、背景、任务清单、约束条件、输出格式、验收标准这六件事讲清楚他能一次性把活干到你满意的概率会提高十倍。Claude Code 的提示词也是这个逻辑。六大要素分别是角色定义告诉模型它是谁具备什么能力倾向。比如“你是精通 Vue3 和 Vue Router 的资深前端工程师”这能让模型调整技术决策的倾向性。项目背景说明当前项目是什么、技术栈是什么、已有的基础设施有哪些。模型知道的信息越多生成的代码越贴合项目实际。任务清单用编号列出要做的事和必须覆盖的功能点。功能点越具体越好别用“完善”这种虚词。约束条件明确哪些能做、哪些不能做。比如“请求必须走项目已有的 request 封装不要新增 axios 实例”、“不要修改现有路由文件新增独立路由模块”。约束是防止模型自由发挥的紧箍咒。输出格式告诉模型先给什么、再给什么、代码按什么结构组织。比如“先列文件清单再按文件逐个输出代码每个文件开头注释职责”。验收标准给出你判断“做完了”的标准让模型自检。比如“组件复用切换路由时必须重新请求数据”、“必须处理请求竞态”。这六个要素不是每次都要写全但写全了生成的代码质量会稳定很多。尤其当你面对的是一个多文件、跨组件、涉及路由和状态管理的复杂页面时缺任何一个要素后面都得多花几轮对话去补课。2.2 动态路由场景下的要素写法要点拿动态路由详情页来说有几个地方需要特别花心思。第一是任务清单里要写明路由参数的变化场景。我吃过的亏是提示词里只写了“根据 id 获取文章数据”模型自然就写了一个 onMounted 里请求数据完全没有考虑从一篇切到另一篇的情况。后来我在任务清单里明确写“从 /article/1 跳转到 /article/2 时组件是复用的需要监听路由参数变化并重新请求数据”它才把watch补上。第二是约束条件里要写清竞态处理。很多人不会想到跟 AI 提“竞态”这个词但你不提它大概率就漏了。我实际验证过明确写了“必须处理请求竞态只展示最新一次请求的结果”Claude Code 会主动用请求序号或者取消旧请求的方式去处理。这个能力它是具备的只是默认不会给你加。第三是状态保持不能只写一句“返回列表页时保持页码不变”。你要给它线索比如“列表页使用了 keep-alive 缓存返回时需要恢复滚动位置和页码”它才会去检查keepAlive配置、scrollBehavior设置是否是配套的。第四是 404 的处理策略。动态路由的:id可能是非法字符串也可能是库里不存在的 ID这两种情况要不要区分提示词里写清楚“文章不存在时渲染 Not Found 组件而不是停留在空白页”模型就会在接口返回 404 时做对应处理而不是简单 console.error 一下完事。把细节写进提示词看起来像是在“照顾”模型其实是提前替自己省掉后续的追问和调试时间。一句话提示词一时爽后面排查火葬场。3. 完整案例实操从提示词到可运行详情页3.1 我的提示词原文下面是我在博客 CMS 项目里实际用过的提示词技术栈是 Vue3 Vite TypeScript Vue Router 4 Pinia接口统一走/api/request封装。原样贴出来你可以根据自己项目调整# 角色 你是一名精通 Vue3、TypeScript、Vue Router 4 的资深前端工程师擅长复杂动态路由页面的开发与状态管理。 # 项目背景 我负责的技术博客 CMS 前端使用 Vue3 Vite TypeScript Pinia接口统一通过 src/api/request.ts 封装的 request 函数请求接口基础路径是 /api。现在需要新增文章详情页路径为 /article/:id。 # 任务 实现文章详情页包含以下功能 1. 根据路由参数 id 从 GET /api/articles/:id 获取文章数据id 非法时直接展示 404 页面。 2. 页面模块包括文章标题、作者信息、发布时间、封面图、正文Markdown 渲染、标签列表、评论区列表、相关文章推荐。 3. 组件加载期间显示骨架屏加载失败显示错误提示与重试按钮。 4. 从 /article/1 跳转到 /article/2 时组件复用必须监听路由参数变化并重新请求数据。 5. 处理异步请求竞态只展示最新一次请求的结果防止旧响应覆盖新页面。 6. 文章不存在接口返回 404时渲染项目现有的 NotFound 页面。 7. 详情页返回列表页时列表页页码和滚动位置保持不变请检查项目是否已启用 keep-alive 并配置对应路由 meta。 # 约束 - 使用 Composition API 的 script setup 语法样式使用 scoped。 - 请求必须走 src/api/request.ts 的 request 函数不要新增 axios 实例或 fetch。 - 评论区和相关推荐拆分为独立组件放在 src/components/article/ 目录下。 - Markdown 渲染使用项目已有的组件遇到图片懒加载配置不要改动。 - 不要修改现有路由文件的逻辑采用独立路由模块文件接入。 - 生成代码必须完整可运行不要省略任何 import 语句。 # 输出格式 1. 先列出需要新增和修改的文件清单及每个文件的职责。 2. 再按文件逐个输出完整代码文件开头用注释说明职责。 3. 最后给出路由注册方式说明 meta 字段为 keepAlive 时的注意事项。 4. 输出完成后对照任务清单逐条检查指出你尚未覆盖的条目。这个提示词的关键词是“任务-约束-输出-自检”四段式看起来挺长但每个词都有用。比如明确说“不要省略任何 import 语句”是因为 Claude Code 生成多文件代码时经常在展示时省略 import导致你复制到项目里一堆报错。3.2 生成结果的关键代码拆解Claude Code 第一轮就给了完整的文件清单src/views/article/ArticleDetail.vue、src/components/article/CommentList.vue、src/components/article/RelatedArticleList.vue、src/router/article.ts。其中核心的详情页组件大概长这样和普通代码不同它把竞态和参数监听都处理了script setup langts const route useRoute() const router useRouter() const article refArticle | null(null) const loading ref(true) const error ref() let requestSeq 0 const fetchArticle async (id: string) { const currentSeq requestSeq loading.value true error.value try { const { data } await requestArticle({ url: /articles/${id} }) if (currentSeq requestSeq) { article.value data } } catch (e: any) { if (currentSeq ! requestSeq) return if (e.response?.status 404) { router.replace(/404) return } error.value 加载失败请重试 } finally { if (currentSeq requestSeq) { loading.value false } } } watch(() route.params.id, (id) { if (typeof id string /^\d$/.test(id)) { fetchArticle(id) } else { router.replace(/404) } }, { immediate: true }) /script这个实现里requestSeq就是竞态处理的实用手段每次请求前序号加一响应回来后只有当前序号是最新的才更新数据。Claude Code 能写出这段不是因为它多“聪明”而是因为我的提示词里明确说了“只展示最新一次请求的结果”它需要做的只是挑一种实现策略。路由配置这边它给了独立文件router/article.tsimport type { RouteRecordRaw } from vue-router export const articleRoutes: RouteRecordRaw[] [ { path: /article/:id, name: ArticleDetail, component: () import(/views/article/ArticleDetail.vue), meta: { keepAlive: false, title: 文章详情 } } ]keepAlive: false是我在提示词里要求它检查并配置的结果。详情页本身不需要缓存但列表页需要这两个 meta 如果搞混了后面的状态保持逻辑会连环出错。3.3 一次追加对话把状态保持需求补上第一轮生成后我检查了列表页的滚动位置保持。Claude Code 在提示词里已经输出了检查结论列表页组件没有被keep-alive包裹所以需要在路由出口处补配置并在列表页恢复滚动位置。我直接追加了一句话请按照你刚才的检测结论修改 App.vue 中的 RouterView 缓存策略使列表页路由组件进入 keep-alive并补全 ScrollBehavior 配置要求返回时滚动位置和页码都能恢复。它很快给出的方案是在RouterView外层加KeepAlive :include[ArticleList]然后在scrollBehavior里对带savedPosition的路由恢复滚动位置。这里有个小细节keep-alive的include匹配的是组件 name不是路由 name它帮我检查了列表页的defineOptions({ name: ArticleList })是否存在这个细节对新手很有用。实际跑起来之后从列表页进详情页再返回页码和滚动位置确实都保留了。这个功能不是提示词里一开始就有而是第二轮追加对话引导出来的。这说明一个方法论第一轮提示词解决“主链路”第二轮追加解决“边界状态”两者结合才能做出真正可用的页面。4. 常见问题排查Claude Code 生成动态路由的典型坑4.1 路由参数名不匹配导致白屏Claude Code 生成代码时路由文件里定义了path: /article/:id组件里却用了route.params.articleId或者直接写死了一个route.query.id。这种情况在 AI 生成多文件代码时特别常见因为它在写组件时可能“记不清”路由里参数叫什么就会自己猜一个。排查方法很简单打开页面看路由地址再对照组件里取的参数名不一致就改组件。更好的办法是在提示词里就把参数名固定下来比如明确写“路由参数统一使用 id组件通过route.params.id获取禁止使用其他参数名”。一次说不清后面生成 3 个页面你就要改 3 次。4.2 组件复用时完全不重新请求这是动态路由页面最有代表性的问题。场景是在文章 A 详情页点击推荐区跳到文章 BURL 变了但页面内容还是文章 A。原因就是组件实例复用onMounted不会重复执行。如果生成代码里没写watch(() route.params.id, ...)你就要让 Claude Code 补上。我习惯的提示词是“当前组件实例会在路由参数变化时复用请添加对 route.params.id 的监听并在回调中重新调用数据请求函数同时保留 loading 状态。”如果 AI 生成了监听但没设置{ immediate: true }首次进入页面就不会请求数据这也是一个容易漏的小点。4.3 刷新后页面 404 或空白动态路由页面对服务端配置有要求。开发环境 Vite 自带 history fallback 没问题但生产环境如果是 Nginx地址/article/123刷新时 Nginx 找不到对应文件就会返回 404。Claude Code 不会知道你的部署环境它只负责前端代码。这块不能在提示词里完全解决但可以提示它“输出部署注意事项”让模型主动告诉你需要配置try_files $uri $uri/ /index.html;。对开发来说我一般把它列为上线前检查项跟打包构建一起过一遍。如果页面在本地开发正常、上线刷新就 404优先检查这个。4.4 错误处理被忽略很多 AI 生成的详情页只有一个请求成功的路径没有失败处理。接口 500、超时、断网的情况下一律空白。我测试时模拟过一次断网页面直接卡在 loading 状态转个不停。原因就是finally里的 loading 结束逻辑没写。提示词里的“功能 3”我明确提了“加载失败显示错误提示与重试按钮”它才在 catch 里补上 error 状态和重试按钮。这里有个小技巧把“重试”当成一个明确功能来提不要只写“处理错误”否则 AI 往往只是console.error一下根本不做 UI 反馈。4.5 列表页返回时状态丢失详情页做完了返回列表页时发现页码回到第一页、滚动位置在顶部这也是高频问题。原因有两层路由组件没有缓存返回时重新创建自然回到初始状态或者有缓存但滚动位置没有恢复。排查思路是先看列表页组件有没有被KeepAlive包含再看scrollBehavior是否做了savedPosition处理。如果两者都配了还是不行要检查KeepAlive的include正则是否匹配组件 name。这个坑我踩过至少两次都是 name 大小写不一致导致的静默失败。问题现象可能原因排查切入点进入页面白屏参数名不匹配检查 route.params 与路由定义是否一致切换文章内容不更新未监听路由参数补 watch route.params.id加 immediate上线刷新 404服务端未配置 fallbackNginx try_files / 部署平台路由配置接口失败无提示缺少错误处理和重试检查 catch 分支和 finally 状态返回列表页码丢失keep-alive 未配置检查 include 匹配组件 name、scrollBehavior5. 提示词迭代技巧把一次会话变成可持续维护的资产5.1 让 AI 先自检再交付我现在的习惯是凡涉及多文件、多状态的项目提示词末尾一定加一条“输出完成后对照任务清单逐条检查指出你尚未覆盖的条目”。这一条能让 Claude Code 自己把漏掉的功能主动说出来而不是让你逐条盯着代码去翻。有一次它看了自己的输出承认“任务 6 中 404 路由未配置只在代码里做了 replace 但 NotFound 页面未接入”我只需要追加一句“请补充路由配置”就解决了。这种自检机制比你自己 review 几十行代码高效得多尤其是当你同时对多个文件做改动的时候。5.2 把验证过的提示词变成团队模板同一个项目的多个动态页面比如商品详情页、用户主页、订单详情页它们的路由参数、组件复用、竞态处理逻辑大同小异。我会把第一次验证有效的提示词存成模板每次新建页面时替换掉接口路径和页面模块清单其他部分不动。这样既保证一致性也降低每次从头写提示词的认知负担。模板维护有一点要注意技术栈升级或者项目基础设施变化比如请求封装换了参数形式模板里对应的约束条件要同步更新否则 AI 会持续生成过期用法。我踩过一次坑request 封装返回结构改了模板没改两台新页面都是按旧接口格式写的顺手就全错了。5.3 给 AI 提供错误现场加速修复Claude Code 生成代码后如果运行报错不要只说“这代码跑不起来帮我修一下”。它没有本地运行环境看不到你的报错详情。更好的做法是把报错信息直接复制给它包括浏览器 console 的报错栈、接口返回的状态码、页面的表现现象。信息越具体它越能定位到准确的代码位置。比如有次页面报Cannot read properties of null (reading title)我把堆栈和场景发过去它直接判断是初始化时 article 为 null模板里又索引了 article.title然后给出可选链方案article?.title加默认值。整个过程不到 10 秒比你自己一行行检查快太多了。以我个人实际操作的经验来说Claude Code 这类工具的价值不取决于你会多少命令而取决于你能不能用提示词把“模糊需求”翻译成“精确规格”。动态路由详情页这个案例前前后后我迭代了四轮提示词从第一轮的不堪用到最后一轮基本不用改靠的就是不断把项目里的约定、边界和验收标准塞进提示词里。你每一次补充的细节都在替未来的自己省时间。