{T}

组件库实战:复制功能开发

本章我们主要讲解“复制到剪贴板”功能的开发。这个功能点看似简单,但因为涉及到多平台交互和平台的“黑盒”机制,所以变得异常复杂。在开发过程中,我们花费了大量时间与 AI 反复“拉扯”,整个过程充满了意外和挑战。这段经历能让我们深刻体会到 AI 辅助编程的真实边界。


实现复制功能

一开始我是按照拆分的 “阶段六:复制功能” 的任务描述开发的,网页上预览区是没什么问题的。最主要是复制到微信公众号。

粘贴到微信公众号后发现各种问题,反复的让 AI 修复,一直未果。以下是粘贴到微信公众号后的预览效果:

以为是这里的任务描述有问题,就点了回退。直接输入需求、技术文档,让 AI 做为参考实现微信公众号复制功能。如下所示:

从 HTML 源码到富文本

AI 生成后,打开预览,点击“复制” 按钮后,粘贴到公众号编辑器的不是格式优美的图文,而是一堆毫无样式的 HTML 源代码。也同样存在各种问题,决心一个一个修复吧。

以下是我们把问题抛给 AI,它自己的分析结果: “浏览器默认的复制行为,如果没有明确指定,会将富文本作为纯文本(Plain Text)处理。这导致所有 HTML 标签都以字符串的形式呈现。”

AI 迅速定位了问题,并指出需要使用 Clipboard APIwrite 方法,并传入一个指定类型为 text/htmlBlob 对象。这确保了剪贴板中的内容被正确识别为富文本。

这个问题还算顺利,一次解决了。之后就是最前面看到的公众号预览效果。

核心交锋:伪元素的“消失”与 AI 的“想当然”

解决了源码问题后,我们很快发现了第二个、也是更棘手的一个问题:预览区域中,每个大标题前起装饰作用的蓝色竖线,在复制后消失得无影无踪。

我向 AI 描述了“竖线丢失”的问题。AI 的诊断还是精准的,它立刻指出“伪元素是根本原因”,并自信地给出了解决方案。看它那么自信的描述,我以为这次修复十拿稳稳。

然而,现实给了我一记重击:应用 AI 的修复方案后,问题依旧。

这正是我们与 AI 交锋的第一个关键回合。AI 拥有丰富的“知识图谱”,它知道伪元素是什么、有什么特性。但它的第一次尝试却暴露了其能力的短板:它提供了理论上正确的方向,却没能给出实践中可行的代码。

我不得不再次向 AI 施压,要求它进行二次修复。这一次,AI 调整了策略,提出在复制前,动态地遍历所有带竖线的标题,手动创建一个 <span> 元素来模拟伪元素,并将其插入到标题内容的前面。

这个方法其实也可以。如果不懂或不细看它的解决方案可能就这样处理了。我认为不太好的原因是,这是为了解决一个问题而打的补丁,既然不支持,为什么不在一开始就解决呢?

于是,我向 AI 提出了我的看法:“这个方案是在复制时动态处理,每次复制都要执行一遍,不太好。我们应该从根本上解决,直接在预览组件里把伪元素换成真实的 HTML 元素。”

这才是更彻底、更优的解决方案。在我的引导下,AI 最终修改了 Previewer 组件的实现,用一个真实的 <span> 标签代替了 ::before 伪元素。

这个过程的教训是:AI 有时能快速定位“是什么”,但在“怎么做”的层面,它倾向于选择最直接的“补丁”方案,而缺乏对代码架构和长期维护性的考量。人类开发者的经验和架构判断力在这里能起到关键的“导航”作用。

连锁反应:一个修复引发的另一个 Bug

正当我以为可以松一口气时,第三个问题接踵而至:竖线是出现了,但它的颜色与预览区域的显示效果不一致。预览中是优雅的蓝色,复制后却变成了默认的黑色。

经过排查,能看到 AI 也发现竖线的颜色是通过 CSS 变量定义的。在我们之前的修复中,复制元素时丢失了其计算后的样式。AI 生成的代码并没有智能到去解析 CSS 变量,获取其最终的色值,再作为内联样式(inline style)赋予新的元素。

这又是一轮与 AI 的“拉扯”。上面提出问题 AI 解决后,发现还是无法生效,继续指出颜色不一致的问题。

经过这样一番折腾,竖线的颜色问题才最终得以解决。这个 bug 完美地诠释了“修复一个 bug,引入另一个 bug” 的开发怪圈,不只人为会犯错,AI 有时也会同样的犯错。

代码块缩进:平台“黑盒”引发的难题

经过上面一系列的“拉扯”,标题的竖线问题总算解决了。但新的问题出现在代码块上。从最开始的预览效果就能看到,代码块在微信公众号上每一行都挤压在了一起,完全没有了代码应有的缩进和格式。

这个问题非常棘手,因为我们的预览区域是完全正常的,只有在粘贴到微信公众号这个我们无法控制的外部环境中,问题才会复现。这意味着 AI 缺乏足够的上下文去分析问题根源。我和 AI 就这个问题反复交互了多次,始终无法解决。

在这种情况下,我意识到不能再简单地向 AI 描述“代码块坏了”,而是要像一个侦探一样,一步步收集线索,并将这些线索喂给 AI,引导它破案。

第一步:确认被复制的 HTML 内容是否正确

我首先需要知道,我们复制到剪贴板里的 HTML 到底是什么样子的。于是,我让 AI 修改复制功能,在执行复制操作时,将完整的 HTML 源代码打印到浏览器的控制台中。

在浏览器开发者工具的 Console 面板,我看到了打印出的源代码。为了验证这段代码本身是否能被正确渲染,我将其复制出来,粘贴到一个在线的 HTML 预览工具中。结果显示,渲染完全正常,代码的缩进和格式都得以保留。

这个步骤证明了:我们的代码生成的 HTML 是没有问题的。问题出在微信公众号的编辑器上。

第二步:对比审查元素,找到“消失的空格”

既然问题出在公众号,那它到底对我的 HTML 做了什么?我决定用“审查元素”功能一探究竟。

首先,我在渲染正常的在线 HTML 工具中打开开发者控制台,鼠标右键选择 “检查”,发现代码的缩进是通过 <span> 标签包裹的普通空格来实现的。

然后,我将同样的内容粘贴到微信公众号编辑器中,用同样的方式审查元素。真相大白了:微信公众号的编辑器把我 <span> 标签里的空格给“吃”掉了!

显然,微信公众号的富文本编辑器有自己的处理逻辑,它会过滤或压缩掉它认为“多余”的空白字符。

第三步:寻求外部“专家”,找到解决方案

这个问题已经超出了常规前端开发的范畴,涉及到特定平台的“怪癖”。当时已经用 AI (Claude 4) 帮我分析了,但没有这方面特定知识的情况下,很难给出解决方案。

于是,我尝试求助外部的“专家”——腾讯自家的模型“混元”(Hunyuan)。我直接向它提问:“以下 HTML 源代码复制粘贴到微信公众号中,代码块下 SPAN 中的空格没有了,导致代码块看起来没有了缩进,请给我查找问题原因”。

“混元”给出的答案非常精准,直指问题核心:微信公众号编辑器会压缩普通空格,解决方案是把普通空格替换成不会被压缩的 HTML 实体 &nbsp; (No-Break Space)。

第四步:指导 AI,精准修复

有了明确的解决方案,我回到 Trae,向 AI 发出了一个非常具体的指令:“Markdown 代码块渲染为 HTML 时,空格要使用符号 &nbsp; 来代替,请找到这块逻辑进行修改”。

这一次,AI 没有再走弯路。因为它得到的指令不再是“修复格式问题”这样模糊的描述,而是“把 A 替换成 B”这样清晰明确的任务。AI 迅速定位到了处理代码块的逻辑,并成功地将空格替换为了 &nbsp;

最终,代码块的复制问题得到了圆满解决。

“幽灵” Bug:!important 与平台的保存机制

就在我以为问题已解决,准备收工时,一个更诡异的“幽灵” Bug 出现了。

将内容粘贴到微信公众号后,在点击“保存”按钮之前,所有样式,包括代码块的内外边距、标题前的竖线,一切都看起来很完美。

然而,只要我点击微信公众号的“保存”按钮,一部分样式就瞬间消失了!代码块上下左右紧紧地贴在一起,标题前的竖线也无影无踪,仿佛从未存在过。

我再次向 Trae 求助,描述了“保存后样式丢失”的现象。但 AI 对这种特定平台的内部机制显然一无所知,在进行了各种修改之后发现越改越乱,无法给出有效的解决方案。

侦查过程:从审查元素到外部求助

有了之前的经验,我直接开始手动“侦查”。

  1. 审查元素,对比差异:我分别在保存前和保存后对代码块进行审查。

    • 保存前:能清楚地看到 padding: 24px !important; 样式是生效的。

    • 保存后padding 样式已经消失得无影无踪。

  2. 形成假设,求助“外脑”:问题很明显,微信公众号在“保存”这个动作上,触发了一套更严格的样式清洗机制。我带着“为什么保存后 padding 样式会消失”的疑问,再次请教了腾讯“混元”大模型。

    “混元”的回答非常关键,它指出了核心原因:“微信公众号为了保证内容的安全性、兼容性,会在保存时触发严格的样式校验和渲染规则。!important 声明的样式,很可能在部分编辑器的严格模式下被过滤或覆盖。”

最终一击:给出精准指令

真相大白!罪魁祸首就是我们为了确保样式生效而大量使用的 !important。它在我们自己的预览环境和微信编辑器的临时状态下是有效的,但却无法通过微信最终的“保存审核”。

我立刻回到 Trae,向 AI 发出了新指令:

code
一点击微信公众号的保存按钮,保存之后代码块上方、下方、左边的的间距就没有了。经排查原因是加了 `!important` 导致的,把 `!important` 去掉就好了。

目前发现微信公众号一点击保存, H2 到 H6 前面的竖线也没有了,请检查相关逻辑,是否也和 `!important` 有关系”

这次,AI 终于可以大显身手。因为它要做的不再是模糊的“修复 bug”,而是精准的“全局删除 !important”。AI 迅速地扫描了所有相关的 CSS 逻辑,移除了所有画蛇添足的 !important 声明。

至此,这个与“复制功能”相关的所有问题,才被彻底解决。

但这里还有一个谜团,发现有些样式是有 !important 的,但在微信公众号平台也能生效,有的就不生效,这种平台机制就像黑盒一样,需要逐步摸索。

总结

总而言之,这次复制功能的开发经历告诉我们,AI 是一个强大的执行工具,但它并非万能。在面对定义清晰的任务时,AI 表现出色。但当问题涉及复杂的上下文和不可控的平台“黑盒”时,AI 的局限性便会显现。此时,开发者的角色就变得至关重要。我们需要像侦探一样去发现线索,利用经验和工具为 AI 补充关键信息,并给出精准指令。最终,人与 AI 的高效协作,才是解决复杂问题的关键。