微信小程序 AI 对话页的 Markdown 渲染实践:轻量解析、流式输出与两个样式坑

举报
yd_296967770 发表于 2026/11/05 15:31:28 2026/11/05
【摘要】 记录在微信小程序 AI 对话页落地 Markdown 渲染的方案:自研无依赖轻量解析器、流式输出时的增量解析与兜底,以及 word-break 与表格 flex 两个样式坑的定位和修复。

最近在做一个 AI 提示词助手类微信小程序,其中对话页(分镜 / 视频提示词生成)有个绕不开的需求:AI 的回复是 Markdown 格式的,有标题、列表、代码块和表格,如果只当纯文本显示,可读性很差。这篇文章记录一下我在小程序里落地 Markdown 渲染的方案,以及过程中踩的两个很隐蔽的样式坑。

为什么自研一个轻量解析器

小程序对包体积敏感,现成的 Markdown 库要么体积偏大,要么依赖 DOM,而小程序的渲染层并不提供真正的 DOM。实际观察 AI 回复里用到的语法,其实很集中:标题、有序/无序列表、引用、代码块、表格、分割线,再加上行内的加粗、斜体、删除线、行内代码和链接。

所以我写了一个无依赖的轻量解析器(一个单独的 JS 文件),只做这批语法:

  • 块级解析按行扫描,识别标题、列表、引用、围栏代码块、表格和分割线;
  • 行内只做单层解析,不追求嵌套格式的完整还原,避免复杂度失控;
  • 表格的对齐标记统一按左对齐处理,这是刻意的取舍,移动端窄屏下差异并不明显;
  • 代码块单独带复制按钮,链接在小程序里不能直接打开,就做成点按复制。

解析结果是一组带位置 key 的结构化块,页面再用模板把块渲染出来。key 按位置生成有一个好处:流式输出时,除末尾正在增长的块之外,前面块的 key 保持稳定,节点不会被整体重建。

流式输出:80ms 增量解析

AI 回复是流式返回的,一个字一个字往外吐。如果每来一个片段就全量重新解析、全量 setData,手机上很快就会卡。我的做法是把解析做节流:流式期间每 80ms 做一次增量解析,只更新当前消息对应的数据。

还有一个容易忽略的点:解析必须有兜底。流式到一半时,Markdown 往往是不完整的,比如围栏代码块还没闭合、表格只写了一行。如果解析器在这种半成品输入上抛异常,整个流式渲染就会卡死。后来我给渲染入口包了一层 try/catch,解析异常时直接退回纯文本显示,等内容完整了自然又能解析成富文本,用户侧无感。

踩坑一:行内代码被从单词中间截断

样式调完后我截了张图检查效果,发现行内代码断行很怪:update:modelValue 被断成了 update:modelV 和 alue,export default 也被从中间劈开。

原因在容器上的一行 CSS:word-break: break-all。它允许在任意两个字符之间断行,对中文没问题,对英文标识符就是灾难。改法是换成:

.md {
  overflow-wrap: break-word;
}

这样只在空格、标点处优先换行,实在放不下的超长字符串才会断开,行内代码恢复正常。

踩坑二:表格列被压扁,横向滚动失效

第二个坑在表格。最初单元格用了 flex: 1,想着让各列均分宽度,结果内容再长也被挤进屏幕宽度里,外层明明写了横向滚动,却根本滚不起来,列全被压扁了。

后来改成让列宽由内容决定,并给单个单元格加一个上限:

.md-table-cell {
  flex: none;
  max-width: 560rpx;
}

flex: none 后,窄表格照常显示,超宽表格可以左右滑动;max-width 则防止某一格里有一段超长文本,把整张表撑得过宽,超过上限就在格内换行。

滚动跟随的一点教训

流式输出时视图要自动跟随到底部,但用户一旦手动上滑看历史,就不该再把他拽回去。这件事不能靠猜滚动事件去反推用户意图,更稳的做法是直接跟踪触摸状态:记录用户是否正在触摸、是否在拖动,再配合一个短暂的惯性窗口和程序滚动后的锁定时间,决定要不要继续跟随。另外还有个很现实的教训:排查这类问题时,先确认自己测的是不是最新构建——我曾经对着旧包调了好几轮,最后发现新代码根本没跑起来。

小结

在小程序里做 Markdown 渲染,我的体会是三点:第一,按实际用到的语法做减法,轻量解析器完全够用,包体积和可控性都更好;第二,流式场景下一定要考虑「内容不完整」这个中间状态,解析要有兜底,渲染要有节流;第三,移动端的样式问题往往不在复杂逻辑,而在一行 word-break、一个 flex: 1 这种小地方,截图逐项对照检查是最快的定位方式。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。