Codex 明明会写 Vue,我为什么还坚持让它先读代码再动手
前两篇我分别讲了两件事:当前任务的提示词应该怎样做减法,以及前端项目的上下文应该怎样按需提供。
上下文给清楚以后,是不是就可以让 Codex 直接开始写代码了?
我的答案通常还是:先别改,先读。
原因并不是 Codex 不会 Vue3,也不是它不认识 Element Plus。恰恰相反,它越熟悉这些通用技术,越容易快速补出一套看起来合理的实现。
问题在于,通用上合理,不等于放进当前项目就正确。
一个成熟前端项目真正难读的部分,往往不在语法,而在那些没有写进需求、只存在于代码关系里的事实:
-
状态到底由页面、组合式函数还是 Pinia 维护。
-
接口参数在哪一层转换。
-
公共组件的默认行为被哪些页面依赖。
-
权限是在路由、指令还是按钮逻辑中判断。
-
异常提示已经由请求层处理,还是需要页面自己处理。
-
某个看似重复的方法,是否为了兼容不同业务路径而保留。
如果这些内容没看清,Codex 仍然能写出代码,而且经常写得很快。真正的风险是:它可能用一套更“标准”的实现,替换掉项目里已经形成的业务约定。
所以我说的“先读代码”,不是形式上的分析步骤,而是修改前建立工程证据。
AI 会写框架代码,不代表它已经理解当前项目
我会把这两种能力分开看。
第一种是技术能力:
-
知道 Vue3 Composition API 怎样组织状态。
-
知道 Element Plus 表单和表格怎样使用。
-
知道 TypeScript 类型怎样定义。
-
知道请求、Loading、异常和分页的一般处理方式。
第二种是项目理解:
-
知道这个仓库选择了哪一种组织方式。
-
知道相同能力已经封装在哪里。
-
知道哪些旧行为不能在本次任务中改变。
-
知道修改一个局部文件会影响哪些调用方。
-
知道项目用什么方式证明改动没有破坏现有功能。
第一种能力让 Codex 能“写出来”,第二种能力才决定它能不能“写进去”。
前端项目里最常见的返工,很多不是代码不能运行,而是代码没有进入项目原有的系统。
例如,一个页面需要增加导出按钮。通用实现可能是直接请求文件流、创建下载链接,再在页面中处理成功与失败。可当前项目也许已经有统一下载方法,负责文件名解析、错误响应识别和权限提示。
如果不先读代码,新实现也许能够下载正常文件,却会绕开项目已有的错误处理。正常路径看起来完成了,异常路径则变成新的不一致。
这类问题仅靠“请遵守项目规范”解决不了。Codex 必须先找到规范在代码里的具体落点。
跳过阅读,最容易产生四类“局部正确”
我对 AI 生成代码的一个基本判断是:局部正确很容易,全局合适更难。
修改前不读代码,最容易出现下面四种结果。
第一类:语法正确,状态归属错了
假设要给订单列表增加一个状态筛选。下面只是演示场景,不代表真实项目。
Codex 看到页面后,可以很自然地新增一个响应式变量:
const orderStatus = ref('')
然后查询时把它加入请求参数。
单看这几行没有问题。但项目里也许已经把查询条件、页码和每页数量统一放在 queryParams 中,重置、翻页、缓存恢复都围绕这个对象工作。
新变量脱离了这条状态流,可能出现:
-
重置时忘记清空。
-
返回页面时无法恢复。
-
导出仍从 queryParams 取值,导致查询和导出条件不一致。
-
页面上的筛选值与请求对象出现两个来源。
AI 没写错 Vue,它只是没有读出“状态的唯一来源”。
第二类:功能正确,项目封装被绕开
前端项目常见的公共能力包括:
-
请求方法。
-
消息提示。
-
弹窗。
-
Loading。
-
权限指令。
-
文件下载。
-
日期和枚举转换。
如果只读目标页面,Codex 可能看不到这些封装,便会直接使用框架或组件库的原生能力。
结果是功能能用,却多出一套实现。
这种代码最容易在审查时被一句“项目里不是这么写的”打回来。问题不在 AI 不会复用,而在任务开始时没有让它查清楚“复用对象在哪里、谁正在使用、行为是什么”。
第三类:当前页面正确,调用方被破坏
修改公共组件时,目标页面只是一个使用者。
例如给公共表格组件增加默认空值展示,如果只看当前页面,直接把所有空值统一变成“--”似乎很合理。但其他调用方可能区分:
-
数字 0 和空值。
-
空字符串和未返回字段。
-
可编辑单元格的空状态。
-
插槽已经自行处理的内容。
公共组件内部的一处默认行为变化,可能让多个页面一起改变。
这时“读代码”不能停在组件文件本身,还要查 Props、Emits、Slots、默认值以及主要调用方。否则,局部页面上的优化可能是全局回归。
第四类:正常路径正确,异常路径丢了
AI 很容易从方法名和模板结构中识别正常流程,但项目中的异常约定经常藏在更深的位置。
比如:
-
请求拦截器已经统一提示部分错误。
-
页面只处理需要保留输入的业务失败。
-
取消请求不应该显示错误。
-
组件销毁后返回的旧请求不能覆盖新页面状态。
-
权限变化需要重新获取数据,而不是只隐藏按钮。
如果只围绕“点击按钮后成功做什么”阅读,生成结果很可能只覆盖正常路径。
这也是为什么我不会把“编译通过”当成理解项目的证据。类型系统能发现一部分错误,却不能告诉我状态责任、异常边界和业务行为是否接对。
我让 Codex 先读的,不是整个仓库
“先读代码”很容易走向另一个极端:让 Codex 把整个项目分析一遍。
这同样没有必要。
修改一个用户列表,不需要先理解所有业务模块;调整一个弹窗,不需要把整个组件库逐个总结。阅读范围应该围绕当前行为逐层扩展。
我通常从下面六个入口开始。
1. 项目规则
先看当前任务适用的 AGENTS.md、本地 Skill 或目录规则,确认:
-
哪些实现方式必须遵守。
-
哪些检查必须执行。
-
哪些目录或文件应优先阅读。
-
哪些操作需要停下来确认。
规则负责告诉 Codex“怎样在这个仓库里工作”,但规则本身不能替代代码现状。
2. 技术与运行入口
查看 package.json、构建配置、入口文件和路由,确认:
-
实际框架与关键依赖。
-
可用的项目脚本。
-
页面怎样进入。
-
当前功能属于哪一个应用或子模块。
这里不是为了背版本号,而是防止读错构建体系、读错应用入口,或者执行一个项目根本不存在的检查命令。
3. 目标功能入口
从路由、菜单、页面或组件入口进入当前功能,确认:
-
用户操作从哪里开始。
-
页面由哪些子组件组成。
-
数据在何时加载。
-
哪些行为是页面自己负责的。
只要入口找错,后面读得越认真,方向越可能偏。
4. 数据和状态流
沿着一次真实行为继续查:
用户操作 → 事件处理 → 状态变化 → 参数转换 → 接口调用 → 响应处理 → 页面渲染
列表查询、弹窗提交、分页切换、权限控制,都可以沿这条链检查。
读到这里,Codex 应该能说清楚“谁拥有状态”和“状态在哪些节点变化”,不能只列出几个方法名。
5. 相近的正确实现
找一个当前项目里经过确认的参考页面或组件,比较:
-
命名方式。
-
组件组织。
-
状态归属。
-
请求和异常处理。
-
加载与反馈。
-
验证方式。
参考实现不是用来整段复制,而是用来识别项目已经做出的选择。
6. 影响范围和验证入口
最后查:
-
目标组件或方法的调用方。
-
相关类型和接口。
-
现有测试。
-
构建、类型检查和页面验证方式。
阅读到这里,才算从“怎样写”走到了“改完会影响谁、怎样证明没有破坏”。
OpenAI 当前的 Codex 代码库理解用例也采用相似思路:先限定要理解的功能区域,再追踪请求流、模块职责、校验、状态变化和潜在风险,最后指出下一批应该阅读的文件和需要执行的检查。
我认为其中最值得注意的一点是:有用的阅读结果应该是一张具体地图,而不是文件列表。
“我已经读过了”不能作为完成信号
Codex 可以很快总结文件内容,但总结不等于理解。
我不会用“已经阅读 8 个文件”判断阅读阶段是否完成,也不会因为它把目录结构复述了一遍就允许开始修改。
我会看它能不能回答下面六个问题:
-
本次行为从哪个入口触发?
-
核心状态由谁维护,唯一来源在哪里?
-
请求参数和响应数据在哪一层转换?
-
哪些公共能力必须复用?
-
这次修改可能影响哪些调用方和异常路径?
-
修改后用哪些现有检查和页面路径验收?
如果其中两三个问题仍然只能用“可能”“大概”“看起来”回答,就说明阅读还没结束。
这时应该继续查证,而不是把猜测写进修改计划。
我会要求阅读结果区分事实、推断和未知
这是我判断 AI 是否真正理解项目时最常用的一个动作。
阅读报告里的结论,应该分成三类:
已确认事实
能够指出文件、方法或调用关系作为依据。
例如:
用户列表的查询条件和分页均由 queryParams 维护;handleQuery 会先将 pageNum 设为 1,再调用 getList。
合理推断
代码表现出某种意图,但没有足够证据证明它是项目规则。
例如:
角色列表和用户列表都使用同一种重置顺序,推测这是当前后台列表的通用行为,但尚未找到明确规则。
尚未确认
业务或技术上存在多种答案,代码也不一致。
例如:
请求失败时是否保留表格旧数据,两个相近页面处理不同,需要业务确认。
这三类内容不能混在一起。
AI 最危险的不是有未知,而是把推断写成事实,再基于它连续修改多个文件。
一段“先读后改”的任务写法
我会把阅读阶段单独写成一个可验收任务:
## 当前阶段 只理解用户列表的查询与重置流程,暂时不要修改代码。 ## 阅读入口 - 项目规则和当前任务适用的 Skill - 用户列表路由与页面入口 - 用户接口模块 - 公共分页组件 - 一个已确认的相近列表页面 ## 需要回答 1. 查询、重置和翻页的完整状态流。 2. 页面、公共组件和接口层分别负责什么。 3. 必须复用的现有方法或封装。 4. 本次修改可能影响的调用方和异常路径。 5. 项目实际提供的检查命令与页面验证路径。 ## 输出要求 - 每个关键结论附对应文件或代码位置。 - 将结论分为已确认、推断和未知。 - 列出下一步建议阅读的文件及原因。 - 发现规则冲突或行为不一致时暂停,不要自行选一个实现。
这段任务不要求它写一行代码,但产物并不抽象。只要输出足够具体,我就能判断它是否找对了入口、读清了状态、发现了风险。
哪些任务不需要单独安排阅读阶段
不是所有修改都要先写一份项目分析报告。
改一处已经定位明确的文案、修正一个孤立的类型拼写、调整一个没有复用关系的局部样式,通常可以边读边改。
我会在下面几种情况中单独保留阅读阶段:
-
任务跨越页面、组件、接口或状态层。
-
目标文件存在多个相近实现。
-
修改公共组件或公共方法。
-
需求会改变状态流、权限或异常行为。
-
当前项目不熟悉,或者历史代码风格不统一。
-
一旦理解错误,会产生较大范围返工。
决定是否先读,不看任务描述有多长,而看错误理解的成本有多高。
先读代码,不是拖慢 AI,而是把错误暴露在代码产生之前
Codex 的实现速度很快,这也是为什么阅读阶段更重要。
方向没确认时,生成速度越快,错误假设扩散得也越快。一个状态归属判断错误,后面可能连着影响请求、重置、导出、缓存和测试。
在代码生成前发现“这里有两套分页模式”“这个组件还有六个调用方”“错误提示已经统一处理”,修正成本很低。
等代码改完再发现,面对的就不只是一个错误判断,而是一整片建立在它上面的差异。
所以我不会把“先读”理解成保守,也不会把“直接改”理解成高效。真正应该比较的是:
哪一种方式能用更低的总成本,得到可验证、可维护的结果?
对有状态、有调用关系、有项目规范的前端任务来说,先读相关代码,通常是控制总成本的一部分。
下一篇我会把这一步继续落细:让 Codex 读完以后,我会要求它先交一张“前端项目地图”。这张地图应该包含什么、怎样避免只做目录介绍、什么信号说明它已经足够支撑修改,我会给出一份可直接复用的模板。
本系列持续更新。Day 4 的第二篇会从“为什么先读”进入“读完应该交付什么”,继续把 AI 协作变成可验收的工程流程。
参考资料
更多推荐

所有评论(0)