VibeCoding最佳姿势
VibeCoding最佳姿势
作为一名每天和代码打交道的 Android 工程师,我见证了 AI 如何彻底改变编程。现在,一个最前沿的词汇正风靡开发者圈子——Vibe Coding(氛围感编程/情绪流编程)。
简单来说,Vibe Coding 就是你只管提需求、出思路、把握方向(负责 Vibe),而把敲键盘、写具体代码的脏活累活全丢给 AI。
这是否意味着不懂编程的普通人也能轻松写出复杂的软件?答案是:能,但有前提。 很多人用 AI 写代码,刚开始很顺,到后面功能一多,代码就变成了一团乱麻(俗称“屎山”),完全无法维护。
如何让不懂编程的你,也能用 AI 写出容易迭代和进化的高质量代码?以下是我为你整理的“工程师级”实战指南。
一、不要说完产品形态就启动编码
非编程人员最容易犯的错误,就是一开始就追求完美,恨不得把所有能想到的功能一次性堆砌出来。你可能会兴奋地 向 AI 描述一个完整的产品形态 ,比如要做一个带推荐算法、实时聊天、会员体系、后台管理面板的社交平台,连字体配色和动效细节都交代得清清楚楚。这种热情完全可以理解,但在 VibeCoding 的节奏里,现有的AI编码大概率不能很好的完成开发工作,Cursor和CC这种辅助编码工具的工程设计和其背后的LLM模型已经很强大,但是依然不能完全理解透彻你的需求,急于求成恰恰是最危险的起点。
当你把一整部产品说明书丢给 AI 时,它并不会像资深工程师那样帮你拆解任务,反而会 因为上下文过长、约束条件过多而迅速“失焦” ,这种在业内叫噪声太多。
最后要么是生成一堆看似完整实则到处报错的代码,要么是开始胡言乱语,把不同框架的语法混在一起,让你连调试都无从下手。更糟的是,作为非专业程序员,你很难分辨哪些是致命错误、哪些可以暂时忽略,最后只会被满屏的红字搞得心力交瘁,误以为编程太难、自己不适合。
所以这一章的核心思想就是四个字:先窄后宽。不要说完产品形态就启动编码,而是按照现实中技术团队开发一个需求的流程,与AI配合,一步一步搭建出最终的形态。
1. 选择生态最成熟的技术
面对琳琅满目的技术名词,你可能会被一些听起来酷炫的小众框架吸引,觉得那是更高级的选择。但在 VibeCoding 这个环境中,技术的“酷”远不如“稳”重要。
成熟生态意味着三件事:
- AI 的训练数据里这种代码最多,它写起来最熟练;
- 网上任何报错信息几乎都有人遇到过、解决过,你复制粘贴就能自救;
- 当你卡住时,随便问一个懂点技术的朋友或者继续追问 AI,都能获得可理解的答案。
所以不要让自己的产品从技术选型开始就进入困难模式。你的第一句提示词可以这样写:
我要做一个记账本微信小程序,或者一个 Web 网站,或者一个桌面应用,请为我选择一个生态最成熟、报错最容易解决、社区讨论最多的技术栈,并给出理由。
把这段话当作你的第一道安全锁。AI 给出建议后,你只需要确认它选的是不是那种”大家都用过、教程一搜一大把”的方案,比如 React、Vue、微信原生开发、Python 加 Flask 或 Electron 这类老牌选手。即便你完全不懂它们是什么,也至少确保自己这次开发任务走在了坑最少的路线上。
举个实际例子。当你向 AI 提出上面那句话之后,你可能会收到这样的回复:
AI 推荐方案:React + Vite + Tailwind CSS
推荐理由:
- React:全球使用率最高的前端框架,GitHub 上拥有 230k+ star,社区极其活跃。任何你遇到的问题几乎都有人遇到过并已解决。
- Vite:新一代前端构建工具,零配置即可启动项目,开发服务器秒开,对新手极其友好。
- Tailwind CSS:原子化 CSS 框架,不需要你会写样式,直接在 HTML 中加类名就能做出漂亮的界面。
总结:这套组合是目前 Web 开发领域生态最成熟、教程覆盖最广、AI 训练数据最多的技术栈之一,非常适合 VibeCoding。
AI 选好技术栈后,你只需要一行命令就能让整个项目骨架出现在眼前:
npm create vite@latest my-bill-app -- --template react
AI 会帮你生成这样一个干净的项目结构:
my-bill-app/
├── index.html # 网站的入口文件
├── package.json # 项目的配置文件(记录依赖、脚本等)
├── vite.config.js # Vite 的配置文件(通常不需要动)
├── src/
│ ├── App.jsx # 你的主要代码就写在这里
│ ├── App.css # 样式文件
│ ├── main.jsx # 程序的启动入口(不需要动)
│ └── index.css # 全局样式
└── public/ # 放图片、图标等静态资源
每个文件职责清晰,你接下来绝大部分时间只需要和 App.jsx 打交道。这就是一条被无数人踩过的、最平坦的路。
跑通最小闭环
选定技术栈之后,绝对不要急着去写登录注册、数据库连接或者漂亮的主页。你在这个阶段的唯一目标,就是让这个 AI 生成的空壳程序在你的电脑上 真正地跑起来 。
它可以是网页上弹出一句 Hello World,可以是小程序开发工具里出现一个空白页面,也可以是桌面应用弹出一个带标题的空窗口。无论形态多寒酸,只要它是由你亲自启动,并在你的屏幕上按照预期渲染出来的,这就是一次伟大的胜利。
为此,你应该要求 AI 给你一步步的配置指南,细致到怎么安装环境、怎么打开终端、怎么输入命令、怎么把运行结果截图给你看。哪怕这个过程看起来像在机械地复制粘贴,也请耐心做完。这相当于在给后续所有开发工作打地基。很多非程序员在这一步因为环境报错而产生强烈的挫败感,误以为是自己操作失误。其实恰恰相反,环境配置本身就是整个开发链路中变数最多的一环,不同的操作系统、不同的软件版本都会引发奇怪的问题。正因如此,才更需要让 AI 帮你把这条路先走通,而不是让它去写那些花哨的功能代码。事实上,现在的编程工程工具,都可以帮你走这一步,在背后运行命令自己做环境验证,失败后会分析报错信息尝试其他配置方案。
如果环境没跑通,后面写再多完美的代码都是废纸,因为你连看都看不到它们运行起来的样子。空壳一旦跑通,你就获得了一个可以随时把新功能装进去的活体容器。接下来哪怕每次只加一个按钮、一个输入框,你都能立刻看到反馈,这种即时的正反馈正是 VibeCoding 最迷人的地方。反之,如果一开始就带着几十个功能一起上,一旦出错,你根本不知道是环境的问题、代码的问题,还是 AI 理解错误,排查的难度会让整个项目迅速烂尾。
让一个最简陋的空壳运行起来。这步走稳了,后面的一切才有了真正生长的土壤。
以我们的记账本项目为例,整个最小闭环的搭建过程就是下面这几步。你可以把这些命令直接复制给 AI,让它帮你逐条解释,然后一条一条执行:
# 第一步:确保你的电脑上有 Node.js(AI 会教你安装)
node --version
# 第二步:用 Vite 创建项目骨架(一行命令搞定)
npm create vite@latest my-bill-app -- --template react
# 第三步:进入项目目录
cd my-bill-app
# 第四步:安装项目依赖(AI 已经帮你列好了需要的库)
npm install
# 第五步:启动开发服务器
npm run dev
执行完最后一步,你的终端会显示这样一行输出:
VITE v5.x.x ready in 350 ms
➜ Local: http://localhost:5173/
用浏览器打开 http://localhost:5173/,你会看到一个带有 React 图标和计数器的默认页面。这就是你的第一个里程碑。 此时你的项目里只有这些真正在起作用的文件:
my-bill-app/
├── index.html
├── package.json
├── vite.config.js
└── src/
├── App.jsx # ← 以后你的代码就写在这里
├── App.css
├── main.jsx
└── index.css
和上一节的项目结构一模一样,没有任何多余的东西。空壳跑通了,接下来每写一行新代码,你都能在浏览器里立刻看到效果。
二、小步快跑,只实现“少量核心模块”
环境跑通之后,你手上有了一个活着的空壳,这时候想要往里填东西的冲动会非常强烈。但请克制住一口气把所有功能都告诉 AI 的念头。第二章要解决的核心问题就是如何从零开始堆积功能,同时让整个开发过程始终处于你能够掌控的范围。最有效的策略是小步快跑,也就是一次只实现一个极其微小的功能,做完之后立刻动手验证,确认它真的能用,再继续下一个。
这个原则听起来简单,做起来却容易被遗忘。因为人在有了一个跑起来的界面之后,很容易产生“不如我让 AI 顺便把登录、存储、动画一起做了”的贪心想法。但你要意识到,VibeCoding 里的 AI 就像一位记忆力有限的搭档,你交给它的任务越集中、约束越少,它给出的代码就越不容易出错。一旦你试图一步到位,把好几个并不相关的逻辑塞进同一个提示里,AI 极有可能在各部分之间产生隐含的冲突,而你却很难定位问题到底出在哪儿。
1. 切蛋糕思维
很多人对功能的想象是一整块蛋糕,总想一口气吞下去。比如你想要一个带记账功能的待办清单,脑袋里出现的可能是“帮我写一个记账待办清单应用”。这句话对 AI 来说太过庞大了,它会同时试图处理界面布局、数据存储、计算余额、交互逻辑等一系列事情,最终产出的很可能是一团无法运行的乱麻。
正确的做法是把这块蛋糕切成能一口吃下的小片。你可以把刚才那个需求拆成两个极其纯粹的步骤,甚至更细。第一步只要求实现能输入文字并显示在列表上,其他什么都不要。这意味着 AI 只需要写一个输入框和一个展示列表,不需要考虑删除、编辑、持久化或任何运算。你拿到代码后立即运行,确认输入文字确实能出现在列表中,这一步才算真正完成。第二步再去要求实现点击按钮能删除这条记录。此时 AI 只需要在已有的能显示列表的基础上加入删除功能,改动范围很小,出错的概率大大降低。
下面是我们的极简记账本按照切蛋糕方式演进的实际过程。每一步只做一件事,每一步的代码都是可运行的状态。
第一步:只做输入+列表展示。 你对 AI 说:“请在 App.jsx 中实现一个输入框,输入文字后按回车,文字出现在下方的列表中。不要做删除、不要做存储、不要做任何额外功能。”
AI 会生成类似这样的代码:
// App.jsx — 第一步:只有输入和展示
import { useState } from 'react';
function App() {
const [text, setText] = useState('');
const [items, setItems] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
setItems([...items, text]);
setText('');
}
};
return (
<div>
<h1>极简记账本</h1>
<form onSubmit={handleSubmit}>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="输入一条记录"
/>
<button type="submit">添加</button>
</form>
<ul>
{items.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
</div>
);
}
export default App;
运行 npm run dev,在输入框里打几个字,按回车,文字立刻出现在下方。此时你的项目结构依然极简:
src/
├── App.jsx # 只有这一个文件被修改过
├── App.css
├── main.jsx
└── index.css
第二步:增加删除功能。 你确认上一步没问题后,再对 AI 说:“请在上面的代码基础上,给每条记录后面加一个删除按钮,点击后该记录从列表中移除。”
AI 只会在已有的 items.map 里多加一个按钮,改动范围很小:
// 仅展示改动部分 — 在 <li> 中增加删除按钮
<ul>
{items.map((item, i) => (
<li key={i}>
{item}
<button onClick={() => {
setItems(items.filter((_, index) => index !== i));
}}>删除</button>
</li>
))}
</ul>
第三步:增加金额输入和余额计算。 你对 AI 说:“现在每条记录除了文字还要包含金额(数字),在列表顶部显示总金额。请只修改 App.jsx,不要引入新文件。”
AI 会把 text 扩展为 {text, amount} 的对象,加上一个金额输入框,然后在顶部计算总和。代码变多了,但仍在一个文件内,逻辑完全在你可控的范围内。
每一步做完、跑通、确认,再走下一步。三次迭代之后,你的 App.jsx 从 20 行变成了约 50 行,但始终只有一个文件,项目结构没有膨胀。
这种切蛋糕思维本质上是在人为地控制每一次 AI 生成的复杂度。每完成一小片,你都可以亲手验证它的实际表现,一旦哪里不对劲,你马上就能知道是刚才那一步引入的问题。它让调试从一个让人绝望的全黑盒子变成一个可以逐步排查的透明过程。
2. 每次修改都要看到反馈
切碎功能只是手段,核心在于验证闭环。每让 AI 帮你写完一个微小功能,不要急着告诉它“接下来再帮我加一个 XXX”,而是立刻在电脑上运行一遍。看一眼界面,确认没有报错,操作一下看效果是否符合预期。这个过程只需要几十秒,却能帮你节省未来可能耗费好几个小时的大范围排查工作。
这样做有两个直接的好处。第一,错误的存活时间极短。如果上一个功能是好的,加完新代码后一运行就崩了,你百分之百可以断定是刚才加的这段代码搞砸了,马上让 AI 修复它。第二,你获得的是一种连续的、实实在在的正反馈。每运行成功一次,你对整个项目的掌控感和信心就增加一点。这种稳步推进的节奏远比埋头写了一大堆代码然后一次性运行看到满屏报错要健康得多,也更容易让你坚持把项目做完。
以我们上面第三步(增加金额计算)为例,你完整的验证闭环就是这样一个极短的清单:
✓ 打开浏览器 http://localhost:5173/ — 页面正常显示,没有白屏
✓ 输入"午餐"、金额"35",点添加 — 列表中出现了"午餐 ¥35"
✓ 输入"咖啡"、金额"18",点添加 — 列表顶部余额显示 ¥53
✓ 点击"咖啡"旁边的删除按钮 — 余额变回 ¥35
✓ 刷新页面 — 数据还在(或不在,都可以接受,下一步再加持久化)
整个过程不到一分钟。五个勾全部打上,你就可以放心地进入下一个功能。如果哪一个勾没打上,你知道问题就出在上一次改动里,直接把上面的代码和错误现象一起扔给 AI,让它定位修复。你不必自己看懂报错信息,只需要做那个”按回车运行、看结果、告诉 AI 哪里不对”的人。
小步快跑的本质就是用可控的节奏换取持续的确定性。每次只添加一个功能,每次添加之后马上验证,你的项目就像一个不断搭积木的过程,每搭一块就确认它稳稳地立在上面。即便后来需要调整,你也知道自己稳稳地站在什么地方。
三、推倒重来,按新架构重构一遍
当一小片一小片的功能逐步累积,你手上可能已经有了几个能跑通的核心模块。但此时的代码多半是凑合着堆在一起的,所有逻辑可能挤在一两个文件里,看上去混乱而脆弱。这时候如果继续往上叠加功能,维护成本会急剧上升,任何小改动都可能牵一发而动全身。 所以必须做一次彻底的整理,这正是专业工程师常说的重构 。
重构的通俗理解不是把代码删掉重写,而是保持所有功能不变,把代码内部的摆放方式重新规划一遍,让它变得规整、清晰、便于以后继续添加新东西。你在第一章和第二章所获得的那些功能,此刻就是你的全部家当,而重构就是要为它们建一座结构合理的房子来安放。
1. 搬家与规范化
你可以请 AI 根据当前已经实现的所有功能,生成一份新的架构文档。然后要求它按照这个新架构,帮你把现有的代码搬到不同的位置。比如把专门负责界面展示的代码放进 UI 文件夹,把处理数据计算和逻辑的部分放进 Data 文件夹,把一些通用工具抽出来放在 Utils 里。这种分家的过程会让每个文件只承担一类明确的职责,以后再想修改界面,你大概知道应该去 UI 文件夹里找,想调整计算逻辑就去 Data 文件夹。
这个过程对于非专业程序员来说可能会有些抽象,你不需要一次性理解所有名词,只要理解一个原则就行:让相关联的代码住在一起,让不同职责的代码互相隔开。AI 完全可以替你完成这个搬家动作,它会按照你的指令把代码切分好,并确保各个文件之间的引用关系依然正确。搬完之后,别忘了运行一次你的程序,确认所有功能都还能正常运作。这就等于完成了一次房屋改造,里面的东西一样没少,但格局焕然一新。
以我们的极简记账本为例,重构前你的所有代码都挤在一起:
# 重构前 — 所有逻辑堆在一个文件里
src/
├── App.jsx # 200+ 行,界面+数据+逻辑全混在一起
├── App.css # 样式也全部堆在一个文件里
├── main.jsx
└── index.css
AI 帮你重构之后,同样的功能会被重新分配到各司其职的位置:
# 重构后 — 职责分离,结构清晰
src/
├── components/
│ ├── TransactionForm.jsx # 专门负责输入表单的界面
│ ├── TransactionList.jsx # 专门负责列表展示的界面
│ └── BalanceSummary.jsx # 专门负责余额计算的展示
├── hooks/
│ └── useTransactions.js # 全部数据逻辑(增删改查)集中在这里
├── utils/
│ └── formatCurrency.js # 金额格式化这样的通用工具
├── App.jsx # 现在只有 ~25 行,只负责组装各个组件
├── App.css
├── main.jsx
└── index.css
代码数量没变,功能完全一样,但每个文件现在只承担一件事。你以后想改界面就去 components/,想调计算逻辑就去 hooks/,改任何一个地方都不用担心无意中破坏另一个无关的功能。
2. 创建编程工具的Harness约束文档
架构清晰之后,真正的挑战才刚开始。你当然可以反复提醒 AI “请遵守我们的架构”,但 AI 的记忆有限,一旦对话变长或开启新会话,它很可能又把界面逻辑和数据运算搅在一起,让你前功尽弃。因此,你必须把刚刚生成的架构说明固化成一份架构约束文档,并 强制要求你使用的 AI 编程工具在真正动代码之前,必须完整阅读这份文档 。
这份文档就是你的 Harness。它像缰绳一样勒住 AI,提前框定什么能做、什么绝不能做、代码必须落在哪个文件夹里。你可以直接让 AI 帮你生成这份文档,只需对它说:根据我们已经完成的重构结构,请生成一份架构约束文档,内容需包含每个文件夹的职责、组件和数据流的边界、命名规范,以及禁止使用的跨层引用。把这份文档保存为项目根目录下的一个固定文件,比如 AI_RULES.md。这样你就拥有了一份白纸黑字的合同。
以下是一份可以直接复制使用的 AI_RULES.md 范例,它就是为上面那个重构后的记账本项目量身定制的:
# AI_RULES.md — 极简记账本架构约束
## 项目概述
基于 React + Vite 的记账本 Web 应用,使用 Tailwind CSS 做样式。
## 文件夹职责
- `src/components/` — 纯 UI 组件,只负责渲染界面,不直接操作数据。每个组件一个文件。
- `src/hooks/` — 自定义 Hook,封装所有数据逻辑(增删改查、计算、持久化)。组件通过调用 Hook 获取数据和操作方法。
- `src/utils/` — 纯函数工具,不依赖 React,可被任何文件引用。
- `src/App.jsx` — 根组件,只负责组装各个子组件,不包含业务逻辑。
## 数据流规则(单向数据流)
1. `useTransactions` Hook 是数据的唯一源头(Single Source of Truth)。
2. 子组件通过 props 接收数据,通过回调函数触发操作,绝不直接修改 Hook 内部状态。
3. 组件之间不直接传递数据,所有共享数据通过 App.jsx 中转。
## 命名规范
- 组件文件:PascalCase(如 `TransactionForm.jsx`)
- Hook 文件:`use` 前缀 + CamelCase(如 `useTransactions.js`)
- 工具函数:CamelCase(如 `formatCurrency.js`)
## 禁止事项
- 禁止在 `components/` 中直接使用 `localStorage` 或 `fetch`
- 禁止在 `hooks/` 中引入 JSX 或 UI 库
- 禁止跨层级引用:`components/` 之间不能互相 import
- 禁止引入未在 `package.json` 中声明的第三方库
接下来是关键一步,让你的工具真正执行这份合同。
如果你使用 Cursor,可以把这份文档配置为项目规则。在 Cursor Settings 的 Rules 中,将
AI_RULES.md添加进去并设为自动应用。此后每次你提出需求,Cursor 都会自动把这份约束注入上下文,AI 在构思代码之前就已经被这些规则包围,生成的代码自然会落在正确的文件夹里,遵循你定好的边界。
类似的:
如果你使用 Claude Code,可以在项目根目录创建一个
CLAUDE.md文件,在里面写明一条铁律:在生成任何代码之前,必须先重新读取并严格遵守AI_RULES.md中的所有架构约束。你也可以在每次重要对话开头直接对 Claude Code 说:”请先读取根目录下的 AI_RULES.md,本轮所有代码生成都必须遵守其中的规定。”一旦养成习惯,你甚至可以把这条指令封装成一个自定义斜杠命令,一键触发。
你的 CLAUDE.md 内容可以非常简短,比如这样:
# CLAUDE.md
## 架构约束
在生成或修改任何代码之前,你必须先读取项目根目录下的 `AI_RULES.md` 文件,
并严格遵守其中定义的所有架构约束。包括但不限于:
- 文件夹职责划分
- 单向数据流规则
- 命名规范
- 禁止事项清单
如果 AI_RULES.md 中的规则与你的默认行为冲突,以 AI_RULES.md 为准。
这样每次新开会话,Claude Code 都会自动加载这份指令,带着镣铐开始工作。
这样做带来的改变是根本性的。过去你是等 AI 写完代码再去检查它有没有把东西放错地方,现在 AI 在动手之前就已经戴上了镣铐。它会自觉把界面代码写进 UI 文件夹,把数据处理逻辑写进 Data 文件夹,不会擅自引入你没允许的库,也不会让不同层级之间的引用乱飞。这种前置约束,远比出错后再返工高效得多。
四、戴着镣铐跳舞,持续进化
完成了重构并锁定了架构约束,你现在拥有的是一个极其坚固且规范的基地。所有旧功能都安稳地待在正确的文件夹里,自动化测试随时可以帮你站岗放哨,AI 在动手之前就必须阅读你的架构文档。
到了这个阶段,你终于可以放心地进入持续进化的节奏,去开发第四个、第五个、甚至第一百个功能。
这里的镣铐不是一个贬义词。恰恰相反,正因为提前给 AI 戴上了这副镣铐,你才获得了真正的自由。你不需要再担心它会把代码写乱,不需要每次都亲自检查文件结构,也不需要在每一次改动后战战兢兢地手动点遍所有功能。镣铐把 AI 的创造力圈定在你可以掌控的范围内,让它在你画好的框里尽情发挥。
在这个阶段,你与 AI 的每一次互动都应该遵循一个固定的循环。这个循环只有四步,每一步都对应一个明确的目的,形成一条不可打断的链条。下面以我们的记账本项目为例,演示如何用这个循环来添加一个”导出报表”功能。
第一步:明确边界。 每次提出新需求时,不要只说”我要添加什么功能”,而是要带上一个前置条件。你可以直接把下面这句话当作模板来用:
我想添加一个”导出为 CSV 报表”的功能:将当前所有记账记录导出为一个 CSV 文件并触发浏览器下载。请严格按照 AI_RULES.md 规定的架构约束来设计,新代码放在对应的文件夹下,不引入新的跨层依赖,不安装新的第三方库。
这句话的意义在于,它强迫 AI 在构思解决方案之前,先认领你的规则。即便工具已经自动注入了约束文档,你再次口头强调一遍,也能有效提升 AI 遵守规则的几率。
第二步:代码注入。 AI 生成代码之后,你需要扫一眼它是否落在了正确的位置。以导出报表功能为例,AI 执行后,你的项目结构会变成这样:
src/
├── components/
│ ├── TransactionForm.jsx
│ ├── TransactionList.jsx
│ ├── BalanceSummary.jsx
│ └── ExportButton.jsx # ← 新增:导出按钮组件
├── hooks/
│ └── useTransactions.js
├── utils/
│ ├── formatCurrency.js
│ └── exportToCsv.js # ← 新增:CSV 导出逻辑
├── App.jsx
├── App.css
├── main.jsx
└── index.css
新增的文件放在了正确的位置——按钮在 components/,导出逻辑在 utils/。几秒钟就能确认,但这一步能拦住”AI 把数据处理写进 UI 组件”这类低级错误。
第三步:拉紧马具。 代码放好之后,立刻运行你的测试。即使你不会写测试,也可以让 AI 帮你生成一份。比如在重构阶段,你就可以对 AI 说:“请为现有的增删改查功能生成一套自动化测试,放在 src/__tests__/ 目录下,确保我每次加新功能时可以一键检查有没有破坏旧功能。“之后每次写完新代码,只需要在终端运行一行命令:
npm run test
你会看到类似这样的输出:
✓ renders transaction list correctly
✓ adds a new transaction on form submit
✓ deletes a transaction on button click
✓ calculates balance correctly
✓ ExportButton renders without crashing
✓ exportToCsv generates valid CSV format
Tests: 6 passed, 6 total
绿色全部通过 → 放心前进。如果出现红色,直接把错误信息复制粘贴给 AI:“新增导出功能后,第三个测试挂了,请在不破坏现有架构的前提下修复。“你不用理解错误的底层原理,测试就是你的客观裁判。
第四步:人工验证。 测试通过之后,花一分钟亲手用一下。对于导出报表这个功能,你的验证清单就是:
✓ 点击"导出 CSV"按钮 → 浏览器弹出文件下载
✓ 用 Excel 打开下载的文件 → 中文不乱码,金额格式正确
✓ 删除一条记录后再导出 → 导出的文件不包含已删除的记录
✓ 页面其他功能正常 → 添加、删除、余额计算都没有受影响
四个勾全部打上,这一轮循环才算真正闭合。现在你可以放心地对 AI 说:“下一个功能。”
这四个步骤合在一起,就是一个持续进化的发动机。你每跑完一圈,就稳妥地新增一个功能,项目在可控的状态下稳步长大。如果按照本文的方法一路走下来,当初那个只有 App.jsx 一个文件的 Hello World 空壳,最终会成长为这样一个结构清晰的中型项目:
my-bill-app/
├── AI_RULES.md # 架构约束(AI 的缰绳)
├── CLAUDE.md # Claude Code 入口指令
├── index.html
├── package.json
├── vite.config.js
└── src/
├── components/ # 界面层:每个组件一个文件
│ ├── TransactionForm.jsx
│ ├── TransactionList.jsx
│ ├── BalanceSummary.jsx
│ └── ExportButton.jsx
├── hooks/ # 数据层:所有业务逻辑
│ └── useTransactions.js
├── utils/ # 工具层:纯函数
│ ├── formatCurrency.js
│ └── exportToCsv.js
├── __tests__/ # 自动化测试:你的安全网
│ └── app.test.js
├── App.jsx
├── App.css
├── main.jsx
└── index.css
从始至终,你没有写过一行从零开始的代码——所有的代码都是 AI 生成的。但你做的每一步决策——选成熟技术、跑通最小闭环、切碎功能逐个验证、推倒重构、用 Harness 约束 AI——这些才是 VibeCoding 真正的核心能力。代码是 AI 写的,但软件是你做的。
这种节奏也许听起来不够刺激,但正是这种不刺激的节奏,能让一个非专业程序员把项目从想法一路推进到真正可用的产品。镣铐从一开始就是你的盟友,它让你戴着它跳舞,而不是在失控的狂奔中跌倒。