
前阵子我想给自己做一个轻量级的 Markdown 编辑器。需求说起来很简单一个网页文件左边写、右边预览不装软件、不登录、不依赖在线服务双击就能打开。正常做法是自己动手写但我当时动了另一个念头——既然豆包这类 AI 工具连代码都能生成为什么不直接让它来写于是我真去试了。试完之后最大的感受是第一版代码确实在很短时间内就出来了但它只停在“看起来能用”的边缘真正让它变成一个我每天愿意打开的工具靠的不是“让 AI 生成了什么”而是“怎么把脑子里那个模糊的编辑器想象翻译成一句句可以验证、可以修改、可以继续扔给 AI 去迭代的指令”。这篇文章想分享的不是编辑器成品而是我用豆包做编辑器完整走了一遍的过程以及我从里面沉淀出来的一套 AI 辅助开发的工作方式。1. 先搞清楚我要的到底是哪一种编辑器1.1 需求起点不是一个产品而是一个趁手的工具先说动机。我为什么放着现成的编辑器不用非要自己做一个不是市面上的工具不好而是没完全踩中我的场景。在线编辑器要联网打开大文档偶尔卡顿桌面编辑器功能全但大部分功能我用不上带笔记功能的工具又绑定自己的数据格式想导出来换个环境很麻烦。我要的东西其实很小固定的几个 Markdown 文件放在某个目录里想改就打开改完按一下快捷键保存旁边能看到最终渲染效果。不需要项目管理、不需要协同、不需要云同步。这个需求规模小、边界清楚、判断标准明确非常适合拿来当 AI 生成代码的试验场。如果你也想试 AI 辅助开发我会建议你同样从这类“给自己用的、小范围的、失败了也不心疼”的工具开始而不是一上来就挑战一个多人协作的复杂项目。1.2 为什么选单文件 HTML而不是桌面应用或在线服务第一个技术决策是形态选择。我选了单文件 HTML把 HTML、CSS、JavaScript 全部塞进同一个文件浏览器打开即用。这个选择有三个原因不需要构建工具没有 Node.js、没有 npm install 那一整条依赖链不依赖服务端本地文件协议直接就能跑后续想改任何编辑器都能打开改不用维护复杂工程结构。这个决策直接影响后面和 AI 协作的方式。单文件意味着所有代码都在同一个作用域里没有模块拆分、没有打包流程、没有跨文件依赖。AI 在这种简单结构下生成代码出错的概率相对低也更容易一次性跑通。如果你让 AI 生成一个依赖一堆 npm 包的项目哪怕它真的写得对本地环境只要有一个版本不匹配你就要额外花掉不少排查时间。1.3 我写给豆包的第一版需求描述刚开始我的提示词写得很随意大致是“帮我写一个 Markdown 编辑器左边输入右边预览。”这行字不算错但信息量接近零。豆包确实返回了一个能打开的 HTML 文件界面布局也对——左边是 textarea右边是 div。但“编辑器”这个词背后的隐含要求太多了语法高亮、光标同步、滚动联动、保存、打开本地文件、快捷键、标题层级渲染、代码块处理……这些我一个都没提它当然不会主动做。这个教训我记了很久AI 生成代码的能力再强它也只会对你说出来的需求负责。模糊的需求得到的就是一个能跑的骨架而不是一个能用的工具。2. 第一次生成看起来像用起来碎2.1 第一版输出一个 textarea 加一个 preview第一版代码的结构如果你也让人工智能写过类似页面应该能猜到一个 textarea 放在页面左边一个 div 放在右边再用一个 Markdown 解析函数把 textarea 的值转成 HTML 塞进右侧的 div。在浏览器里打开的那一刻观感是好的。布局居中背景浅色输入文字后右边确实能渲染出标题、加粗、列表。对一个“编辑器原型”来说验收可以算通过。但这个通过只覆盖了一件事核心链路通了。Markdown 解析、文本输入、渲染更新这条主链路没有断。很多人做到这一步以为 AI 生成的编辑器已经能用了然后直接收工。实际上距离“长期使用”还差得很远。2.2 视觉上通过的背后功能上一碰就碎我实际用了几分钟问题一个接一个冒出来输入速度稍快预览区明显卡顿因为每次敲键都全量重新解析整个文档长文档里滚动时编辑区和预览区完全对不上看完右侧渲染效果要重新找位置不支持保存关掉页面写的内容全没了不支持打开本地 md 文件每次都得手动粘贴进去代码块里的内容被当成普通文本处理解析函数只认得加粗、标题、链接这类基础语法。这些问题有些是功能缺失有些是性能问题但它们不约而同指向一个事实AI 生成的第一版只是帮你完成了从零到一里的那个“一”。剩下从一到一百的部分恰恰是决定这个工具能不能长期留在你日常使用里的关键。2.3 我没有急着删代码而是先记录了一个问题列表当时摆在我面前的选择是让豆包继续改还是自己动手重写。我做的第一件事是把所有问题列成清单按性质分成三类体验类滚动不同步、输入卡顿、光标位置不好找功能类不支持保存、不支持打开本地文件、不支持导出解析类部分 Markdown 语法不支持代码块渲染错误。分类之后思路就清楚了。体验类是优化功能类是补齐解析类是核心正确性。按这个顺序和 AI 沟通每一轮迭代的目标都非常明确。这也是我想强调的一个观点和 AI 协作开发最重要的前置动作不是写提示词而是先建立一份问题清单。清单越具体AI 的每次修改就越有靶心。没有清单的迭代就是你描述一句它猜一句两边都在打空气。3. 把“我想要”翻译成 AI 能执行的提示词3.1 从“写个编辑器”到“写一个具备以下行为的编辑器”第一次生成之后我的提示词风格明显变了。我不再写“帮我写一个编辑器”而是改成“现在有一个单文件 HTML 的 Markdown 编辑器左侧 textarea 输入右侧预览区渲染。请修复以下问题1. 输入时预览区全量渲染导致卡顿请改成防抖在用户停止输入 300ms 后再渲染。2. 请让预览区随着编辑区滚动联动。……”对比前后两种写法差别在于前一种在描述目标后一种在描述行为。行为描述里有输入、有触发条件、有时间参数、有期望结果。AI 对这种描述的理解准确率会高很多。这个转变背后有一个很简单的道理大语言模型对“要什么”的理解往往不如对“做什么、什么时候做、做到什么程度”的理解那么精确。你说“做一个编辑器”它默认给你一个标准形态你说“输入停止 300ms 后重新渲染预览区”它就知道你要的是一个防抖函数。3.2 提示词的结构输入、处理、输出、边界后来我把每次给 AI 的提示词固定成四个部分输入告诉它当前文件是什么、代码结构大概怎样。大部分时候我会直接贴出当前 HTML 文件或者明确说“在现有代码基础上修改”。处理说清楚这次要改什么。一个功能一个功能说不要一次堆五个需求。输出明确交付形式。比如“输出完整的单文件 HTML不要省略 CSS不要用省略号代替代码”。边界告诉它不要动什么。比如“不要修改快捷键绑定”“不要引入外部 CDN 依赖”。这套结构并不高级但非常管用。以前我遇到过一种常见情况AI 理解错了修改位置或者为了改一个功能弄坏了另一个功能。加上边界声明之后这类问题的出现频率明显下降。3.3 一个可复用的提示词模板如果用一句话概括我的模板大概是下面这个样子我正在维护一个单文件 HTML 的 Markdown 编辑器代码结构是 [简述结构]。目前有一个问题[描述现象]。请你在不改动 [说明不许动的部分] 的前提下修改为[描述期望行为]。要求输出完整文件并在代码注释里标出修改位置。这个模板不一定适合所有场景但只要你是在“维护已有代码”而不是“从零生成”这个结构通常比“帮我修一下这个 bug”有效得多。它做了三件事告诉 AI 上下文是什么、禁用区在哪、验收标准是什么。AI 拿到这三样才能往一个准确的方向改。4. 从“能打开”到“能用”编辑器真正麻烦的地方4.1 语法高亮不是简单的正则匹配第二个阶段是功能补齐我第一个想解决的就是语法高亮。没有高亮的编辑器写长文时眼睛很容易累因为标题、加粗、代码块和普通文本在视觉上没有任何层次。一开始我预期“用正则匹配几个规则给对应文字加颜色”但实际遇到的问题比这个复杂。难点在于 Markdown 语法可以嵌套加粗里可以有行内代码代码块内部可能包含多个换行。用正则做简单匹配很容易出现代码块被高亮成普通文本、列表标记被误判为标题符号这类错误。更麻烦的是编辑区里的高亮不能直接用 textarea 实现——textarea 里的文本默认是纯文本你要给不同段落上色就得换成 contenteditable 或引入代码编辑器内核。到这一步豆包给了我两个方向。第一个是换掉 textarea使用一个支持高亮的编辑区第二个是保留 textarea不做实时行内高亮只把高亮做在预览区。我选了更保守的第二个方向。原因是我的核心需求是“写 Markdown 并预览效果”不是做一个代码 IDE。若引入编辑器内核虽然效果更好但还要处理光标跳跃、键盘事件、撤销重做这些内容复杂度和出 bug 的概率都会成倍上升。这个判断很重要AI 没有价值偏好它会按照你的需求给你方案但“什么复杂度合适”只有你自己能决定。4.2 光标位置、滚动同步、焦点管理AI 最容易错的地方编辑器类项目里有三件看起来不起眼、实际最容易出错的小事光标位置、滚动同步、焦点管理。拿滚动同步举例。我最初的需求是“编辑区滚动时预览区跟着滚”。豆包实现的思路是监听编辑区 scroll 事件根据两边滚动高度比例设置预览区 scrollTop。听起来合理但实际用起来有两个问题第一两个区域文档长度不一样总高度不同按比例映射在长文里会越偏越多第二预览区内部的图片和代码块加载完成后总高度会变化导致滚动比例失真。更稳的方案是按锚点同步在编辑区里按标题位置生成锚点滚动时找到当前经过的标题再让预览区滚到对应位置。这个方案更准确但它需要解析文档结构不是一个简单比例映射能搞定的。这类细节只要你没在提示词里点出来AI 很可能用最简单的方式实现。它不蠢但它默认你给的需求是完整的。所以你会发现要在代码里填这些坑前提是你得先意识到坑存在。这恰恰是 AI 替代不了的部分。4.3 保存、打开、导出决定工具去留的三个功能一个编辑器能不能让我长期用我个人觉得由三个功能决定保存、打开、导出。保存浏览器里可以用 File System Access API 直接写本地文件也可以走 blob 下载。前者体验好但兼容有限后者兼容广但每次保存都会产生一个新文件。打开HTML 里放一个 file input选择文件后用 FileReader 读内容填进编辑区。这个功能不难但要注意中文编码和带 BOM 的文件。导出本质是把 Markdown 渲染后的 HTML 单独生成一个文件样式要内联否则用其他方式打开会丢样式。这三个功能我陆续让豆包做了过程不算曲折。真正让我印象深刻的是当我要求“按 CtrlS 保存”时豆包给出的第一版实现里注册了 keydown 监听器为了防止浏览器默认的“保存网页”行为加了 preventDefault。逻辑看着没问题但实际使用中如果用户用输入法输入中文按下 CtrlS 时恰好有候选词弹出来preventDefault 会把输入法候选框的逻辑一起打断。这个坑我折腾了半小时才定位到。原因不是 AI 生成错了而是浏览器本身的输入法事件链就是这么复杂。AI 写出来的前端代码必须经过真实设备、真实输入法、真实浏览器一遍遍跑才能算数。你以为代码“对了”但“对了”和“在真实环境里对了”是两件事。4.4 中文内容和特殊字符我踩到的一个具体坑还有一个和中文强相关的坑值得单独说。我这个编辑器是给自己写中文内容用的文档里会出现大量中文标点、全角括号、以及「」这类符号。第一次用的时候我发现一个规律英文标点前后的语法标记处理得很好但中文标点出现在标题文字或加粗文字里时偶尔会出现转义错误。比如“# 使用豆包整理笔记的体验”这个标题渲染后引号或括号会被错误转换导致标题显示异常。排查到最后问题在于 Markdown 解析逻辑对全角字符的处理不够健壮。解决办法是解析前先对文本做一次 Unicode 规范化处理。但这类问题只要你不拿真实中文内容去测几乎不可能发现。这让我意识到一个原则AI 生成的代码默认是在大量英文语料和英文测试场景下训练出来的它对中文内容的覆盖不一定均匀。所以验证 AI 生成的工具时不能只拿英文测试文本跑一遍流程还要拿自己真实场景里的中文文档做测试。5. AI 生成代码之后我的排查顺序5.1 第一步看现象报错、无反应、还是结果不对AI 生成的代码出问题后我有一套固定的排查顺序。前提是别慌别一上来就说“这段代码有问题重写”。先分清楚现象属于哪一类控制台报错属于代码执行层面的问题顺着报错信息定位页面无反应可能是事件绑定、监听器丢失或初始化逻辑没执行功能结果不对属于逻辑漏洞比如边界条件没处理、状态没更新。把现象分类之后再决定把哪段代码和报错贴回去。最忌讳的是只贴一句“不行”然后让 AI 猜。它会猜但大概率猜不准只会消耗你的时间和耐心。5.2 第二步看输入编码、换行、特殊字符前端项目里很多问题其实是输入问题。常见的有文件编码不是 UTF-8打开后中文乱码文件带 BOM读进来后第一个字符是肉眼看不到的标记Markdown 文档里是 Windows 换行符CRLF正则里用$锚点时行为不一致文档里包含闭合标签字符如果内容直接拼进 HTML会截断标签结构。这类问题用眼睛看往往发现不了因为字符不可见。我通常先把读进来的内容打印出来看长度再看第一个字符的 Unicode 编码而不是直接看渲染结果。5.3 第三步看环境文件协议、浏览器兼容、依赖版本单文件 HTML 在本地双击打开时走的是 file:// 协议。这个协议下很多浏览器 API 的行为会不一样。比如某些浏览器不支持从 file:// 页面里读取本地文件或者对外部 CDN 资源加载有跨域限制。这就是为什么我在这个项目里做得很早的一个决定是不引入任何外部 CDN 依赖。所有依赖包括 Markdown 解析库和样式文件全部下载后内联进单文件。这样文件体积会大一点但避免了“本地打开没样式”“内网加载不了 CDN”这一类环境问题。5.4 第四步看代码逻辑事件、异步、DOM 更新时序如果前三步都没问题才进入代码逻辑层。AI 生成的 JavaScript 代码问题通常集中在三个位置事件绑定事件绑在一个被动态替换的 DOM 节点上节点被换掉后监听器就失效了异步顺序比如保存成功后马上显示“已保存”但文件写入是异步的提示出现在真正完成之前DOM 更新时序数据更新了但视图没刷新原因是渲染函数没有被正确触发。到这一步我经常在关键函数入口加 console.log或者让 AI 给我加临时日志看调用顺序实际是怎样的。这个办法简单粗暴但在 AI 生成的代码里往往最有效因为你不知道它内部怎么组织逻辑靠推理不如靠日志。5.5 一个前端 AI 生成代码的排查清单把前面四步收拢成一张清单我每次遇到 AI 生成代码的 bug基本按这个顺序走层级检查内容常见原因现象报错、无反应、结果不对先分类再决定排查方向输入编码、换行、特殊字符、文件格式UTF-8、BOM、CRLF、全角符号环境file:// 协议、浏览器版本、外部依赖跨域限制、CDN 加载失败、兼容性逻辑事件绑定、异步顺序、DOM 更新监听器丢失、回调时机、渲染未触发这张清单不只适用于编辑器处理任何 AI 生成的前端项目都顺。它最大的价值是帮我在“重写代码”之前先排除掉那些最容易骗人的表面原因。6. 把一次 AI 开发经验沉淀成可复用流程6.1 三阶段流程原型验证、功能补齐、边界加固做完这件事之后我回头看整个流程发现它可以归纳成三个阶段。第一个阶段叫原型验证。目标是让 AI 生成一个能跑的最小版本核心链路不断。这个阶段允许粗糙但必须能运行、能演示、能验证主流程。对应到编辑器就是能输入、能渲染。第二个阶段叫功能补齐。把第一版记录下来的问题清单逐一交给 AI 处理每轮只改一个功能点或一个 bug。这个阶段的核心动作是小步迭代不要一次让 AI 做五件事因为任何一个环节出错你都很难判断是哪件事引起的。第三个阶段叫边界加固。把正常功能之外的特殊情况补上空文档、超大文档、特殊字符、异常编码、浏览器兼容、输入法冲突、快捷键冲突。这个阶段最花时间也是决定工具能不能长期用的关键。6.2 每轮迭代都做最小验证不要一口气加十个功能我给这个过程定了一条规则每一轮完成后必须亲自打开页面按真实使用场景跑一遍确认没问题再进入下一轮。这条规则听起来像废话但实际操作中很容易偷懒。尤其是从 AI 到 AI 的流程里你会忍不住想“它应该改好了吧”结果一验证发现它改好了 A 却弄坏了 B。最小验证的具体做法是每轮改完只测这一轮涉及的功能其他功能不去动。比如这轮是修滚动同步那就只滚滚动条不碰保存功能。这样能保证问题定位准确。如果发现上一轮已经通过的功能这轮又坏了那就要警惕是不是修改引入了冲突。6.3 提示词存档和代码一样值得维护整个项目里我保留了两样东西代码文件和提示词记录。一开始我觉得提示词是一次性输入用完就丢了。后来发现当 AI 生成的代码出问题时最有效的调试资料恰恰是“当时是怎么描述这个功能的”。把提示词和代码放在一起出问题时能快速回溯“它当时到底被要求做了什么”。所以后来我养成了一个习惯每轮迭代前把当前需求、现状、期望行为写清楚存档到一个文本文件。代码改了哪块也在提示词里标注。看起来多花了十几秒但对回顾和复现非常有帮助。6.4 哪些环节适合交给 AI哪些必须自己盯整个过程中我的判断是适合交给 AI 的环节是那些明确的、可描述的、有标准答案的代码生成。比如“写一个防抖函数”“给某个函数补一个文件保存逻辑”“把这些样式统一成变量”。这类任务描述清楚后AI 输出质量通常不错而且速度快。必须自己盯的环节是需求拆解、方案取舍、边界判断和真实环境验证。这几件事 AI 帮不了你选也替不了你验。“要不要引入第三方编辑器内核”“是否接受 file:// 协议下的限制”“保存后如何提示用户”这些决策背后有使用场景和成本考量必须由使用它的人来判断。一句话概括AI 能替你写代码但很难替你决定写什么、不写什么、写到什么程度算完。7. 这件事真正教会我的不是让 AI 写代码7.1 和 AI 协作核心能力从“会写代码”变成了“会拆问题”做这个编辑器的过程让我重新理解了“会用 AI”这件事。以前我以为会用 AI 就是会写提示词比如说得更详细加一些“请逐步思考”之类的技巧。真正做完一个项目才发现提示词技巧只是很小、很表面的一层。真正的核心能力是能把一个模糊的、庞大的、充满隐含条件的需求拆成一个个足够小的、可以被 AI 准确执行的任务。就像做编辑器这件事。表面上我用的是 AI 生成代码的能力实际上我一直在做的是把“编辑器”这个抽象概念拆成布局、解析、高亮、滚动、保存、打开、导出、编码、输入法、性能优化这些子问题然后一个一个解决。这个能力在 AI 出现之前就叫系统设计能力现在它变成了普通开发者也能直接使用的日常技能。你不需要会写每一行代码但你需要知道一个问题应该拆成哪几步每一步的完成标准是什么失败之后怎么排查。7.2 这个方法适合谁不适合谁用 AI 做一个编辑器这件事值不值得复制取决于你属于哪类人。适合的人通常满足这些条件有明确的私人工具需求愿意花一个下午迭代优化有一定的代码阅读和调试基础不追求代码的完美架构只追求能用、够用、可维护。如果你是这类人这个方案很划算——你不用从零写模板代码AI 帮你省掉基础工作量你把精力花在需求和验证上。不太适合的人是那些希望 AI 一次性生成完整产品、自己完全不看代码、不做验证的人。这种情况AI 生成的几百行代码里一旦藏了三个边界问题你会完全无从下手。不是 AI 不行而是 AI 需要一个能看懂它输出、能判断它对不对的协作者。另外如果你想做一个需要长期维护、多人协作、频繁变更需求的产品AI 生成单文件代码的方式也不合适。这时候需要的是工程化模块化、版本控制、测试、代码审查、文档。这些能力不是 AI 的临时生成能替代的而是要在工程体系里认真安排。7.3 如果让我再来一次我会怎么做如果重新做一遍我会调整几件事。第一先自己把编辑器的功能清单写完整再让 AI 动手。第一版我花了太多时间在试错式开发上很多需求是边用边在脑子里冒出来的。如果最初就列出完整需求清单后面能少掉一半迭代轮次。第二优先使用成熟的 Markdown 解析库。这个项目早期我让 AI 自己实现 Markdown 解析后来发现它对不少边缘语法处理得不好。如果一开始就引入成熟解析库这块能省很多事。AI 更适合写应用逻辑而不是去造一个复杂的基础轮子。第三把保存、打开、导出这三个“生存功能”提前到第二个阶段就做。这三个功能不涉及什么复杂度但它们决定了这个工具能否成为每天使用的入口。早一点加进去后续迭代都在真实使用闭环里进行发现问题和解决问题的效率会高很多。回到最初的问题用豆包做一个编辑器值不值我的回答是值而且比预想的更有价值。但价值不落在编辑器本身——它毕竟只是一个单文件工具。真正有价值的是整个过程让我重新理解了一个道理AI 不会替你完成“从想法到工具”的最后一步但它可以把这一步从十公里缩短成一公里半。剩下那一公里半才是你需要真正付出的东西拆解问题的耐心、验证结果的习惯以及对自己需求的清晰认识。这个编辑器现在还在我电脑里我偶尔还会打开它写点东西。每次打开都会想起那个下午我坐在电脑前把一个模糊的想法对着 AI 助手慢慢说出来然后顺着它给的代码一点一点把它变成真东西。这种体验已经不像是“让工具帮我做事”更像是一种新的协作方式正在起作用。