REACT · Vol.VII · LESSON 47 · AI 时代的前端进阶
与 AI 结对编程:V0 / Cursor 提效
AI 编程工具全景:先分清它们各管什么
上一篇第 46 篇,你把 LLM 装进了产品;这一篇换个方向,让 LLM 走进你的工位——用它生成组件骨架、审阅代码、做重构。先把工具地图铺开,因为「用 AI 提效」第一步不是学提示词技巧,而是分清每个工具的粒度和自主度:
| 工具 | 形态 | 最擅长 | 后端世界的类比 |
|---|---|---|---|
| GitHub Copilot | IDE 插件,行级 / 函数级补全 | 你起头它续写,样板代码、单测骨架 | 输入法联想:快,但每次只管一小段 |
| Cursor | AI 原生 IDE,对话改码 | 跨文件重构、全库问答、「把这几处都改掉」 | 坐你旁边的同事:说需求,它动整个代码库 |
| V0 | 网页工具,一句话 / 截图生成 UI | React + Tailwind 组件的「出图」 | 前端外包:交付组件壳,接后端靠你自己 |
| bolt.new | 网页工具,对话生成可运行全栈项目 | 从零起一个能跑的原型站 | 脚手架增强版:五分钟有个毛坯房 |
四者的共同点比差异更重要:产出物都是代码文本,最终都要过你这道 review。差异只在粒度(一行、一个组件、一整个站)和自主度(续写你的思路、还是自作主张铺摊子)。选型不纠结:日常补全用 Copilot 或 Cursor 内置,组件壳找 V0,整站原型试 bolt.new,深度重构留在 Cursor 里慢慢聊。
姿势一:给足上下文——你会写接口文档,就会写提示词
AI 最大的短板不是笨,是不了解你的项目。想想你自己:入职第一周写代码错漏百出,不是能力问题,是上下文问题。AI 每次对话都是「入职第一周」——所以喂什么,生成什么。最好的喂料你早就写过了:第 21 篇用 Zod 写的表单校验 schema、第 28 篇的 Props 接口,它们就是现成的「契约」。契约一给,生成质量立上一个台阶:
// ── ① 契约层:第 21 篇的 Zod schema,字段、校验规则、错误文案全在里面 ──
const orderSchema = z.object({
orderId: z.string().regex(/^ORD-\d+$/, "订单号形如 ORD-1001"),
amount: z.number().positive("金额必须大于 0"),
status: z.enum(["PENDING", "PAID", "CLOSED"]),
});
type OrderInput = z.infer<typeof orderSchema>;
// ── ② 边界层:第 28 篇的 Props 接口,组件对外长什么样 ──
interface OrderFormProps {
initial?: OrderInput;
onSubmit: (data: OrderInput) => Promise<void>;
onCancel?: () => void;
}
// ── ③ 需求层:技术栈、禁止项、验收标准,像验收清单一样写 ──
// 用 React 18 + TS 函数组件 + react-hook-form + zodResolver 实现 OrderForm;
// 不引入 UI 库;提交中按钮 loading 且禁用;错误文案展示在对应字段下方;
// 表单用受控方式管理(第 24 篇),不要用 ref 裸取值。
三层结构记一下:契约层说清数据长什么样,边界层说清组件接口长什么样,需求层说清要它做什么、不要做什么。你会发现这跟给外包公司写的接口文档一模一样——字段、类型、校验、错误码、验收标准写全,交付物才对得上。你会写接口文档,就会写 AI 提示词:同一门手艺,都是把模糊需求翻译成可执行的约束。
给外包只甩一句「做个订单表单」,对方只能自由发挥,返工三次;把接口文档、字段字典、页面原型给齐,一次交付八成合格。AI 就是那个编码速度极快、但对你项目零了解的外包——它不缺手艺,缺文档。你花在「文档」上的十分钟,会在 review 和返工上省回两个小时。
姿势二:小步验证——生成、跑起来、读懂、再提交
新手最常见的翻车姿势:一句「帮我写个完整的订单管理页面」,收下 500 行,贴进项目,跑不起来,也不会改。正确姿势正好相反——把大需求拆小,一次只要一个组件、一个 Hook、一个函数:
// 反例:一次梭哈,生成 500 行黑盒——跑不起来就废,跑起来了也不敢改
// 「帮我写一个完整的订单管理页面,带列表、筛选、分页、详情。」
// 正例:拆成小步,每步一个可验证的交付物
// 第 1 步:「只写 OrderTable 组件,props 收 orders 数组,按第 28 篇的接口定义来。」
// 第 2 步:「加筛选:关键词由父组件传下来(第 14 篇状态提升),别让表格自己管状态。」
// 第 3 步:「分页抽成 useOrderPagination 自定义 Hook(第 13 篇),UI 只管渲染。」
每一步走完,执行一个五拍子的闭环:
- 生成:上下文按第 2 站的三层给足,一次只要一个交付物;
- 跑起来:先让它动,编译错和运行时错当场暴露,绝不攒批;
- 读懂:逐行过一遍,说不清用途的行就是雷——读不懂的代码不敢改,不敢改的代码迟早变祖传;
- 改造:命名、目录、写法对齐项目规范(第 29 篇),别让 AI 风格污染代码库;
- 提交:一笔小 commit,等于通过了一次 code review。
小 PR 三分钟能审明白,500 行的 PR 你只会回一个 LGTM——其实没看。AI 写得越快,你的 review 就越是瓶颈。这不是坏事,它只是把行业真相摆上了台面:判断力才是团队真正的吞吐上限。以前这个上限靠同事的水平的平均值撑着,现在靠你一个人撑着。
姿势三:AI 生成代码必查清单
AI 的错误分布很「偏科」:语法几乎不粘锅,翻车集中在生命周期、类型边界这些需要理解运行时的地方。四项必查,全部是你在这本笔记里学过的:
| 查什么 | AI 的典型症状 | 出处 |
|---|---|---|
| Hooks 依赖数组 | 漏依赖读到旧值(闭包陷阱);或把对象 / 函数塞进依赖,一渲染就重跑 effect,无限请求 | 第 10 篇 |
| 列表 key | 顺手用 index 当 key,排序、删除后界面错位、输入框状态乱窜 | 第 7 篇 |
| 副作用清理 | 定时器、事件订阅、AbortController 不 return 清理函数,切页后还在跑、竞态回填旧数据 | 第 9 篇 |
| 类型偷懒 | 满屏 any 和 as 断言,TypeScript 被用成 AnyScript,契约层形同虚设 | 第 28 篇 |
光背清单没用,得练眼力。下面是 AI 真实风格的「带病代码」——能跑,语法漂亮,但四处带病。先自己找,再看注释:
function OrderList({ keyword }: { keyword: string }) {
const [orders, setOrders] = useState<any[]>([]); // 病灶①:any,字段契约全丢(第 28 篇)
useEffect(() => {
fetch(`/api/orders?kw=${keyword}`)
.then((r) => r.json())
.then(setOrders);
// 病灶②:没有清理函数,快速切关键词会竞态回填(第 9 / 34 篇)
}); // 病灶③:依赖数组没写,每次渲染后都重新请求
return (
<ul>
{orders.map((o, i) => (
<li key={i}>{o.id}</li> // 病灶④:index 当 key(第 7 篇)
))}
</ul>
);
}
发现没有,找茬用的全是前几卷的知识——这就是「判断力」的具象化。这份清单也不是 AI 专属:人写的代码一样要查。区别在于 AI 的错误有固定「偏科」方向,把这几项变成肌肉记忆,AI 生成物的合格率立刻上一个台阶。
V0 实战:从一句话到可运行组件,再手工接后端
用 V0 走一遍完整流程,拿「订单列表页」举例:
- 一句话描述 + 可选截图或草图:「深色订单列表卡片,顶部关键词筛选,状态用彩色徽章」;
- V0 生成 React + Tailwind 组件,数据全是写死的 mock;
- 对话式微调视觉细节,满意后 Copy Code;
- 贴进项目:改文件名、对齐目录规范(第 29 篇),先让它在工程里编译通过;
- 手工接后端:删 mock,换成你自己的取数与状态管理——这一步 AI 替不了,因为它不知道你的接口契约和状态选型。
// V0 交付物里的数据层:写死的 mock,UI 已经七成像
const orders = [
{ id: "ORD-1001", amount: 199, status: "PAID" },
{ id: "ORD-1002", amount: 59, status: "PENDING" },
];
// 手工替换:UI 结构一行不动,只换数据来源
const [orders, setOrders] = useState<Order[]>([]);
const [error, setError] = useState(false);
useEffect(() => {
const controller = new AbortController();
fetch("/api/orders", { signal: controller.signal })
.then((r) => r.json())
.then((data) => setOrders(data.items))
.catch(() => setError(true)); // 加载态 / 错误态:第 34 篇的功课这时派上用场
return () => controller.abort(); // 清理函数——第 9 篇的习惯,此刻最值钱
}, []);
这个流程的分工很清楚:AI 管「形」,你管「骨」。视觉骨架、Tailwind 类名、布局细节,AI 出图的效率是人工的十倍;数据契约、状态归属、副作用纪律,必须你亲手接——因为接错了不会立刻报错,只会在三个月后变成灵异 bug。
所以回到开头那句话:读代码的能力决定你用 AI 的上限。AI 一分钟能产出你一天手写的量,瓶颈整体迁移到「你能多快确认它是对的」。这个能力没有捷径:第 1 到 46 篇的每一篇,都是在给你攒「一眼看出不对劲」的直觉——状态建模(第 4、17 篇)、Hooks 陷阱(第 16 篇)、组件边界(第 27 篇)、TS 约定(第 28 篇)。会用 AI 和不会用的人,差距不在提示词技巧,而在:后者生成十行能改十行,前者生成十行只能全收。
最后列三个风险,都是真实发生过的事故:
- 幻觉 API:一本正经地调用不存在的函数、不存在的 props。TS 编译器是最好的安全网——这也是本笔记坚持「代码默认 TypeScript」的又一个理由;
- 过时写法:训练数据有滞后,它会给你 class 组件、已废弃的生命周期、老版路由。你得能识别「这个写法是哪个年代的」——这正是每篇都讲「为什么」的原因;
- 许可证与保密:生成代码的出处混杂,商业项目留意合规;更重要的是保密纪律——密钥、内网地址、真实用户数据,别贴进任何对话框。
- 工具按粒度选:行级补全(Copilot)、对话改码(Cursor)、UI 生成(V0)、全栈原型(bolt.new),产出物一律当 PR 审。
- 提示词 = 接口文档:契约层(Zod schema)+ 边界层(Props 接口)+ 需求层(栈 / 禁止项 / 验收标准),三层给足。
- 小步闭环:生成 → 跑起来 → 读懂 → 改造 → 提交,拒绝一次 500 行的黑盒。
- 必查四件:依赖数组、key、副作用清理、any 滥用——全是你前几卷攒下的判断力。
- AI 是放大器不是替代品:它会放大你的能力,也会放大你的混乱——读代码的能力决定上限。
本章回顾
这一篇你把 AI 请进了开发流程:会用四类工具、会按「接口文档」的思路喂上下文、会拆小步逐个验证、会按四项清单找茬,也知道了幻觉、过时写法、保密这三颗雷。至此,你和 AI 的关系还是「你一句它一句」的结对模式——它等你发号施令,才敢动一步。但如果它学会自己拆任务、自己调用工具、自己看结果再决定下一步呢?那就是 Agent,一个需要全新界面范式的前端命题。下一站,第 48 篇:Agent 前端——工具调用与状态机。
Comments · 评论