【AI实战:用AI实现前端功能增强的实践分享】
AI实战:用AI实现前端功能增强的实践分享
两个真实案例,一个"需求清晰但技术水深",一个"需求清晰且落地顺畅"——从中窥见AI辅助开发的真实面貌。
引言
在前端开发的日常工作中,我们经常遇到两类需求:一类看似简单,做着做着才发现深处有暗礁;另一类需求清晰明确,只需要高效落地。这两类需求恰好代表了AI辅助开发中最典型的两种协作模式。
本文分享两个真实的AI辅助开发案例:Sheet界面关闭时的自动保存和文件上传新增复制粘贴功能。两个案例都发生在同一个企业级前端项目中(基于Vue 3 + SpreadJS + Element Plus),前者经历了方案迭代、深度Debug、多轮人机协作,后者则是AI快速定位、一次性落地、自动补测试的流畅体验。
通过这两个案例的对比,希望能让读者看到AI辅助开发的真实能力边界——它既不是万能的银弹,也远不止简单的代码补全。
案例一:Sheet界面关闭时的自动保存
需求起点:一个"简单"的想法
最初的需求很朴素:Sheet界面关闭时,提醒用户保存。就像Word文档关闭前的"是否保存更改"一样,看起来是个再常见不过的功能。
我向AI描述了这个需求,AI的第一反应并不是直接给代码,而是先区分了两种"关闭"场景:
- 应用内关闭(关闭tab、切路由、关弹窗):可以完整实现"确认→保存→关闭"的流程
- 浏览器直接关页/刷新:受限于
beforeunload机制,只能做到"提醒",不能可靠地在关闭前完成异步保存
AI还主动分析了项目现有代码,发现脏数据标记已经在记录了(SpreadJS的ValueChanged事件会写入valueChangedData),只是还没有接上关闭拦截。这种"先摸清家底,再出方案"的做法,避免了从零开始的浪费。
方案演进:从不可靠到可靠
需求的演进过程非常有意思:
第一轮:浏览器beforeunload提醒
AI指出当前项目的保存链路很"重"——需要从SpreadJS导出JSON → 生成zip → 包成FormData → 调接口上传。这种重量级操作放在beforeunload里完全不可靠:浏览器不会等你的await跑完就直接关页了。
所以最初落地的是"原生弹窗提醒"方案:有未保存内容时,浏览器弹原生提示,但不指望在关闭瞬间完成保存。
第二轮:30秒防抖服务端自动保存
为了真正"防丢数据",AI建议加入编辑后30秒防抖自动保存。逻辑是:用户停止编辑30秒后,静默调用saveOperateHandle({ silent: true }),将数据保存到服务端。
实现后我发现体验并不理想:
- 如果用户在30秒内关闭了页面,数据还是丢
- 每次自动保存都要走一遍zip压缩+接口上传,资源消耗不小
- 用户完全感知不到"已经保存了"
第三轮:IndexedDB浏览器草稿缓存
我跟AI说"30秒保存好像没什么用,能不能缓存到浏览器?"AI立刻给出了对比分析:
| 方案 | 防误关能力 | 实现成本 |
|---|---|---|
| 30s服务端自动保存 | 弱(30s窗口内丢失) | 已有 |
| IndexedDB本地草稿 | 强(2-5s防抖写入) | 中等 |
最终方案变成了:
- 编辑后3秒防抖写入IndexedDB(比等30秒服务端保存快得多)
- 再次打开页面时,检测本地草稿是否比服务端新,弹窗让用户选择"恢复草稿"或"丢弃"
- 手动保存成功后清除本地草稿
第四轮:移除beforeunload提醒
有了草稿缓存后,我发现每次刷新页面都弹原生提示反而很烦。AI分析后也认同这个判断——beforeunload无法区分"刷新"和"关闭",而草稿缓存已经覆盖了绝大部分场景(除了编辑后3秒内极端关闭的情况),弹窗的价值已经很低。
最终方案变成了:纯草稿缓存兜底,无弹窗干扰,体验最为流畅。
深度Debug:假设-埋点-验证方法论
方案设计很顺利,但真正的挑战来自运行时。实现完成后,我发现编辑内容后并没有自动缓存生效——这开启了一段精彩的Debug过程。
第一个Bug:Vue 3响应式失效
AI在HomeView.vue中用watch监听valueChangedData对象的key数量变化来触发自动保存。但实际运行时,Console中完全没有出现watch触发的日志。
AI提出了四个假设(H-A到H-D),其中最关键的H-C假设是:watch监听的值从未变化。
通过我在浏览器DevTools中看到的日志确认了这个假设后,AI深入追踪了完整的数据流链路,最终发现了一个典型的Vue 3响应式陷阱:
editValueChangedData → toRaw() 取出原始对象 → 在raw上写数据 → Object.assign(reactiveProxy, rawObject)
问题在于:toRaw()取到的原始对象被直接修改后,传给Object.assign时,Vue的set拦截器发现key已存在且值引用未变(hasChanged(sameRef, sameRef) = false),于是不触发响应式更新,watch永远不执行。
修复方案非常精巧:在store中加一个版本号计数器,每次setValueChangedData被调用时递增,watch改为监听这个版本号。零侵入现有数据逻辑,只增加一个触发信号。
第二个Bug:IndexedDB序列化失败
修复第一个问题后,草稿保存流程能触发了,但Console中出现了新错误:
DataCloneError: Failed to execute 'put' on 'IDBObjectStore':
function toString() { [native code] } could not be cloned.
根因是SpreadJS的spread.toJSON()方法返回的对象内部包含native function引用。IndexedDB使用结构化克隆算法存储数据,该算法无法序列化函数类型。
修复同样简洁:写入IndexedDB之前,先用JSON.parse(JSON.stringify(spreadJson))做一次JSON round-trip,自动去除所有不可序列化的字段(函数引用、undefined等),得到纯数据对象。
人机协作的关键模式
回顾这个案例的Debug过程,人和AI的分工非常清晰:
- AI的角色:建立假设矩阵、设计埋点方案、分析日志输出、定位根因、给出修复代码
- 人的角色:在浏览器中执行操作、观察Console日志、将运行时信息反馈给AI
关键点在于:给AI提供精准的运行时信息。当我把完整的Console日志(包括错误堆栈)粘贴给AI时,它能在几秒钟内定位到DataCloneError的确切原因。如果我只描述"保存失败了",排查效率会大打折扣。
案例二:文件上传新增复制粘贴功能
需求一句话说清
需求很直接:在附件上传对话框中,添加文件拖拽和Ctrl+V粘贴功能。这是一个典型的"功能增强"需求——在已有上传组件基础上扩展交互方式。
AI的处理方式:知识图谱 + 代码复用
AI收到需求后的第一个动作不是写代码,而是通过知识图谱定位相关代码:
图谱:上传附件 | 命中 | src/components/spreadOperate/
接着,AI做了一件让我印象深刻的事——它在项目中搜索是否已有拖拽/粘贴的实现,结果发现PenToolDialog.vue中已经有类似的功能。这意味着AI可以复用已有的模式和经验,而不是从零实现。
有了参考实现后,AI制定了一个完整的计划,然后一次性完成所有改动:
- 重构模板,添加拖拽容器
- 在script中补充拖拽/粘贴状态管理和事件处理
- 验证逻辑复用现有的
beforeUpload函数 - 追加样式定义
实现细节的考究
虽然落地很快,但AI在实现质量上并不马虎:
| 功能点 | 实现方式 |
|---|---|
| 拖拽区域 | upload-drop-zone容器监听dragover/dragleave/drop |
| 粘贴上传 | 全局paste事件监听,仅在对话框可见时响应 |
| 数量限制 | 拖拽/粘贴时检查已有文件数+新文件数是否超限 |
| 类型/大小验证 | 复用现有beforeUpload,保持与点击上传一致 |
| 视觉反馈 | 拖拽悬停时高亮蓝色虚线边框+浅蓝背景 |
| 内存管理 | onUnmounted时移除全局paste监听,无泄漏 |
特别值得一提的是,AI主动将纯逻辑提取到独立辅助模块(attachmentUploadHelpers.js),并为其编写了13个单元测试全部通过。这不是我要求的,而是AI基于代码质量的考量自主完成的。
用户体验的微调
功能实现后,我提了一个体验优化:“粘贴、拖拽位置边框希望在没有操作前就浅显一点,方便用户知道拖到哪个位置。”
AI的响应非常迅速——将默认边框从transparent改为Element Plus的标准浅灰色#dcdfe6,让拖拽区域在非悬停状态下也有视觉边界提示。效果:
- 默认状态:浅灰虚线边框,用户一眼看出可拖拽区域
- 拖拽悬停:蓝色边框+浅蓝背景,交互反馈清晰
整个案例从需求到完成,包括代码实现、逻辑提取、13个单元测试、样式微调,一气呵成。
两个案例的对比分析
| 维度 | 案例一:自动保存 | 案例二:拖拽粘贴 |
|---|---|---|
| 需求明确度 | 初始模糊,逐步迭代 | 一开始就很清晰 |
| 方案演进次数 | 4次(提醒→30s保存→IndexedDB→去掉提醒) | 1次(直接落地) |
| 核心挑战 | 运行时环境Bug(Vue响应式、序列化) | 无明显技术障碍 |
| Debug耗时 | 多轮对话+埋点验证 | 无需Debug |
| AI角色侧重 | 方案引导 + 假设验证 + Bug定位 | 代码复用 + 快速实现 + 质量保障 |
| 人的角色侧重 | 需求迭代 + 运行时验证 + 体验判断 | 需求提出 + 体验微调 |
| 最终产出 | 2个新文件 + 2个改动文件 + 9个测试 | 2个新文件 + 1个改动文件 + 13个测试 |
这个对比揭示了一个重要事实:AI辅助开发的效率不仅取决于AI本身的能力,更取决于需求的技术深度和运行时环境的复杂度。
案例一中,AI在方案设计阶段表现优秀——能够分析浏览器API限制、评估不同存储方案的优劣、给出清晰的迭代路径。但到了运行时Debug阶段,AI必须依赖人提供的真实环境信息(Console日志、错误堆栈)才能继续工作。
案例二中,AI几乎独立完成了全部工作——从代码定位、模式复用、逻辑实现到测试编写,人只需要提需求和做最终的体验验收。
实践感悟与经验总结
1. AI擅长的与不擅长的
AI擅长:方案设计、代码生成、模式识别、逻辑提取、测试编写、快速响应变更需求。
真正的难点往往在运行时环境:Vue 3响应式系统的隐式规则(toRaw()导致的reactivity丢失)、浏览器API的安全限制(beforeunload不能可靠执行异步操作)、第三方库的序列化陷阱(SpreadJS的toJSON()返回含native function的对象)——这些问题在代码层面看不出来,必须在真实运行环境中才会暴露。
2. Debug方法论:假设-埋点-验证-定位
案例一的Debug过程展示了一套高效的方法论:
- 建立假设矩阵:AI一次性列出H-A到H-D四个可能的原因
- 设计埋点方案:在关键节点插入console.log,一次覆盖所有假设
- 人执行验证:在浏览器中操作并收集日志
- AI分析定位:根据日志输出确认或排除假设,锁定根因
- 给出修复:针对性修复,不引入额外复杂度
这套流程中,AI和人各司其职——AI负责"想"(建立假设、分析日志、给出修复),人负责"做"(执行操作、观察结果、反馈信息)。
3. 精准的运行时信息是加速排查的关键
当我只告诉AI"没有自动缓存"时,它能做的有限;但当我把完整的Console日志(包含DataCloneError的完整堆栈和触发链路)粘贴过来时,AI在几秒内就锁定了根因。
经验法则:给AI提供的运行时信息越精准越完整,Debug效率越高。Console日志、网络请求、错误堆栈、Vue Devtools的状态快照——这些都是"喂给AI的燃料"。
4. AI会主动考虑代码质量
案例二中,AI在实现功能后主动将纯逻辑提取到独立模块并补充单元测试,这不是我额外要求的。这种行为体现了AI在代码质量上的自觉性——可测试的代码结构、关注点分离、lint检查,这些都是AI"内置"的工程习惯。
5. 好的人机协作模式
经过这两个案例,我总结出的协作模式是:
- 用户负责:需求判断(什么值得做)、运行时验证(在真实环境跑)、体验评审(好不好用)
- AI负责:方案迭代(怎么做最合理)、代码实现(写出可运行的代码)、质量保障(提取模块、补测试、检查lint)
这是一种互补关系:人有对业务和用户体验的直觉判断力,AI有对代码和工程实践的高效执行力。
6. 需求迭代是常态
案例一的需求从"关闭提醒"→"自动保存"→"浏览器缓存"→"移除提醒",经历了四次方向调整。AI在每一次转向时都能快速跟上:理解新方向的合理性、分析对已有实现的影响、给出最小改动方案。
这种"跟随用户思路演进"的能力,在实际开发中比"一次性写出完美代码"更有价值——因为需求本身就是在探索中逐渐清晰的。
结语
两个案例,两种风格。一个是在技术深水区中摸索前行,一个是在平坦道路上高速奔跑。但无论哪种,AI辅助开发的核心价值始终是:让开发者可以把更多精力放在"思考该做什么"上,而不是"研究怎么写"上。
当然,AI不是万能的。运行时的魑魅魍魉(响应式陷阱、浏览器限制、第三方库quirks)仍然需要人去发现和确认。但有了AI作为搭档——它帮你分析假设、写埋点代码、定位根因、实现修复——整个排查过程从"一个人对着屏幕挠头"变成了"两个人高效协作"。
这大概就是AI辅助开发的真正意义:不是替代开发者,而是让开发者的每一分钟都更有价值。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)