从Claude到ChatGPT:我在Prompt工程里踩过的坑和挖出的金子

独立开发路上
2026-04-05 22:37
阅读 599

回国快一年了,刚从硅谷一家中型SaaS公司裸辞回来。说实话,在那边三年多,每天写代码都得配着Lo-fi Hip Hop或者City Pop——不然总觉得少了点灵魂。现在在国内找下一份工作,一边投简历一边复盘自己过去几年在前端交互、动效上折腾过的东西。最近正好被一个老东家项目拉回去救火,顺手把这段时间在AI辅助开发上的“血泪史”整理出来,权当技术分享,也给自己攒点面试谈资。

起因:产品经理又画了个“会呼吸”的按钮

事情发生在上个月底,临近春节前最后一个迭代。产品小哥拉着我们开需求会,甩出一张Figma设计稿:“这个按钮要‘有生命力’,鼠标hover的时候要有轻微的呼吸感,点击要有反馈涟漪,还要支持无障碍……对了,下周三上线。”

我当时差点把耳机摔了——这不就是个普通按钮吗?结果一看动画曲线,贝塞尔函数参数复杂得像解微分方程,还要求60fps丝滑运行,兼容到IE11(别问,问就是客户还在用)。更离谱的是,团队里没人专门做过这种精细交互动效,设计师给的只是视觉稿,没导出Lottie也没给关键帧逻辑。

Deadline压顶,我脑子里第一个念头是:能不能让AI帮我生成基础代码?

于是,我的Prompt工程踩坑之旅正式开启。

第一坑:以为AI是万能码农,结果它连CSS transition都能写错

我先试了ChatGPT(用的是GPT-4),输入Prompt:

“用纯CSS写一个带呼吸效果的按钮,hover时缓慢放大再缩小,循环播放,支持无障碍focus状态”

结果它给了我一段代码,看起来挺像那么回事:

.pulse-button {
  animation: breathe 2s infinite ease-in-out;
}
@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

乍一看没问题,但一跑起来就露馅了——animation在hover时不会暂停!也就是说,鼠标移开后动画还在继续“喘”,完全不符合交互预期。而且focus状态下没有任何视觉反馈,WCAG直接挂掉。

我心想:是不是我Prompt写得太模糊?于是加了约束:

“hover时启动动画,移出停止;focus时加outline;不要使用JS”

这次GPT给了animation-play-state: paused/running的方案,但没处理初始状态,导致页面加载时按钮就在动。更搞笑的是,它建议用outline-offset: -2px来“美化”焦点框——这在深色背景下几乎看不见,测试同学当场翻白眼。

教训一:AI不懂交互上下文,你必须把“什么时候开始、什么时候结束、用户怎么感知”说清楚。

后来我重写了Prompt,明确生命周期:

“默认无动画。仅当:hover或:focus时,启动一个2秒无限循环的scale动画(1 → 1.05 → 1)。移出或blur后立即停止,不留残影。动画必须平滑,且不影响布局流。”

这次终于靠谱了,虽然还是漏了will-change: transform优化,但骨架对了。

第二坑:Claude Code说它懂React,结果Hooks用得像jQuery

不甘心只用ChatGPT,我又去试了Claude 3(Sonnet版本),听说它的Code能力更强。这次我要做一个带进度条的加载动效组件,支持自定义颜色、持续时间、回调。

我给的Prompt是:

“用React函数组件写一个CircularProgress组件,props包括size, color, duration, onComplete。用requestAnimationFrame驱动,不要用setTimeout。”

Claude回了一大段代码,开头是这样的:

import { useState, useEffect } from 'react';

export default function CircularProgress({ size = 40, color = '#3b82f6', duration = 2000, onComplete }) {
  const [progress, setProgress] = useState(0);
  
  useEffect(() => {
    let start;
    const animate = (timestamp) => {
      if (!start) start = timestamp;
      const elapsed = timestamp - start;
      const percent = Math.min(elapsed / duration, 1);
      setProgress(percent);
      
      if (percent < 1) {
        requestAnimationFrame(animate);
      } else {
        onComplete?.();
      }
    };
    
    const id = requestAnimationFrame(animate);
    return () => cancelAnimationFrame(id);
  }, [duration, onComplete]);
  
  // ...render logic
}

看起来挺专业?问题出在useEffect依赖数组——它没包含onComplete的引用变化!如果父组件传的是内联函数(比如() => console.log('done')),每次渲染都会触发effect重新执行,导致动画疯狂重启。典型的闭包陷阱。

更离谱的是,它在render里直接用了style={{ stroke: color }},但没考虑SSR场景——服务端没有window对象,某些构建工具会报错。

我吐槽给同事听,他说:“你指望AI写出生产级代码?它连useCallback都不知道要提醒你!”

教训二:AI生成的React代码,90%需要手动补全依赖数组和边界case。别信它的“最佳实践”标签。

后来我改用更结构化的Prompt:

“写React CircularProgress组件,注意:

  • 使用useRef存储animationId
  • onComplete必须用useCallback包裹后再传入,避免effect重复触发
  • 支持SSR(不能假设window存在)
  • 提供TypeScript类型定义”

这次Claude给出了接近可用的代码,虽然TS类型里漏了onComplete?: () => void的可选标记,但至少骨架健壮多了。

第三坑:Prompt越长越好?结果AI开始“脑补”不存在的需求

有一次我想用AI生成一个粒子背景动画,参考Three.js但希望轻量。我写了个超详细Prompt:

“用Canvas实现一个低CPU占用的粒子系统,粒子从屏幕中心发射,随机方向,带淡出效果。最多200个粒子,FPS不低于50。支持暂停/恢复API。不要外部依赖。提供init、start、stop方法。”

结果ChatGPT不仅实现了粒子系统,还“贴心”地加了鼠标跟随交互、粒子碰撞检测、甚至Web Worker分片渲染——这些我根本没要!代码膨胀到300行,性能反而因为过度设计而下降。

最气人的是,它用了一个全局变量particles,导致如果页面上有两个实例会互相干扰。我问它为什么加碰撞检测,它回:“用户通常希望粒子有物理感。” —— 我当时就想回:“用户只想要个背景动画,不是做游戏引擎!”

教训三:AI喜欢“过度服务”。明确说“不要XXX”比说“要XXX”更重要。

后来我学乖了,在Prompt结尾加上:

禁止添加未提及的功能。不要假设用户需要额外交互。保持代码极简。

效果立竿见影。

对比实测:ChatGPT vs Claude Code 到底谁更适合前端?

为了搞清楚哪个工具更值得投入时间,我做了个小对比实验。用同样的Prompt让两者生成一个“拖拽排序列表”组件(支持touch和mouse)。

维度 ChatGPT (GPT-4) Claude 3 Sonnet
代码长度 180行 150行
是否处理touch事件 是(但没防抖) 是(带touch-action: none)
性能优化 用了transform 用了transform + will-change
错误处理 有try-catch包裹drag逻辑
TS支持 需手动加 默认输出TS版本
可读性 注释较多 逻辑更紧凑

结论:Claude在工程严谨性上略胜一筹,ChatGPT在解释思路上更友好。 如果赶时间看逻辑,用GPT;如果要直接集成,Claude更省心。

不过两家都有通病:对CSS Grid/Flex细节掌握一般,经常写出justify-content: space-around却忘了容器要设display: flex

我的Prompt工程实战技巧(血泪总结)

经过几十次翻车,我总结了几条保命原则:

  1. 角色扮演法:告诉AI“你现在是一个资深前端工程师,正在review新人代码”,它会自动提高标准。

    你是一个有5年前端经验的工程师,请严格检查以下代码的性能、可访问性和兼容性问题...
    
  2. 负面约束清单:明确列出“不要什么”。

    不要使用jQuery风格的DOM操作;不要内联样式;不要假设浏览器支持IntersectionObserver...
    
  3. 分步生成:别指望一次出完整方案。先要架构,再要细节。

    第一步:列出实现呼吸按钮的三种技术方案(CSS/JS/Web Animations API),对比优劣
    第二步:基于CSS方案,写出完整代码
    
  4. 示例驱动:给一段错误代码,让它修正。

    以下代码在hover移出后动画不停止,请修复:
    .btn { animation: pulse 1s infinite; }
    
  5. 上下文锚定:绑定你的技术栈。

    我们项目用React 18 + TypeScript + Tailwind CSS,请基于此生成代码
    

现在回头看:AI不是银弹,但能让你少加班

上周终于把那个“会呼吸”的按钮上线了。最后方案其实很简单:用CSS :hover:focus 触发动画,配合animation-play-state控制启停,加上prefers-reduced-motion适配无障碍。核心代码不到20行。

但如果没有AI帮我快速排除错误路径(比如一开始想用JS轮询),我可能得花两倍时间调试。它像个有点呆但很勤奋的实习生——你得手把手教,但它能帮你搬砖、查文档、写初稿。

回国找工作这段时间,我发现很多国内团队对AI coding工具还停留在“玩具”阶段。其实只要Prompt写对,它真能提升交付效率,尤其是在做那些重复性高、文档不全的交互组件时。

当然,千万别把它当主力开发——毕竟,线上bug不会因为“这是AI写的”就放过你。上周五晚上运维群里@我:“首页按钮动画卡顿,用户投诉了”,我第一反应还是打开DevTools手动调,而不是再去问ChatGPT。


写这篇文章时,我正戴着耳机听YMO的《Rydeen》,窗外是上海阴晴不定的春天。三年海外经历让我习惯了用工具提效,但回国后发现,很多团队还在靠“人肉堆需求”。或许这就是我想找的新机会:既能发挥我在交互动效上的积累,又能推动工程效能升级的地方。

如果你也在探索AI辅助开发,欢迎交流踩坑经验。毕竟,程序员的浪漫,就是把别人的坑变成自己的梯子

(完)

P.S. 投简历的朋友,我司急招前端,要求会调CSS动画、不怕和产品battle、接受偶尔用AI但绝不甩锅给AI——有兴趣私聊!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝