共计 1835 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在 AI 对话系统的开发中,内容展示面临两个核心挑战:

- 动态内容渲染 :AI 生成的响应可能包含代码块、表格、数学公式等复杂结构,需要实时解析和样式处理
- 交互复杂性 :用户可能需要与对话框内容交互(如折叠面板、表单提交、实时预览等),传统静态渲染难以满足需求
技术对比
Markdown 方案
- 原理 :通过解析 Markdown 文本生成 AST(抽象语法树),再转换为 React/Vue 组件
- 优势 :
- 文本体积小(相比 HTML 减少 30%-50%)
- 天然支持版本控制
- 丰富的生态插件(如代码高亮、LaTeX 支持)
- 局限 :
- 动态交互需额外扩展语法
- 复杂布局实现成本高
生成式 UI
- 原理 :基于 JSON Schema 定义 UI 结构和行为,运行时动态生成组件
- 优势 :
- 可声明式描述复杂交互
- 服务端可控制 UI 逻辑
- 类型安全的 props 传递
- 局限 :
- 初始加载体积较大
- 需要维护组件映射表
对比表格
| 指标 | Markdown 方案 | 生成式 UI |
|---|---|---|
| 首屏加载 (ms) | 120-200 | 200-300 |
| 内存占用 (MB) | 5-8 | 10-15 |
| 开发复杂度 | 低 | 中 |
| 交互扩展性 | 需插件 | 原生支持 |
核心实现
React+Remark 方案
import {unified} from 'unified';
import remarkParse from 'remark-parse';
import remarkReact from 'remark-react';
// 类型定义
type MarkdownRendererProps = {
content: string;
components?: Record<string, React.ComponentType>;
};
const MarkdownRenderer = ({content}: MarkdownRendererProps) => {const processor = unified()
.use(remarkParse)
.use(remarkReact, {
createElement: React.createElement,
fragment: React.Fragment,
// 可注入自定义组件
components: {code: SyntaxHighlighter}
});
return processor.processSync(content).result;
};
Vue 动态表单生成器
<script setup>
const schema = {
type: 'object',
properties: {name: { type: 'string', title: '姓名'},
age: {type: 'number', minimum: 18}
}
};
// 组件映射表
const componentMap = {
string: 'el-input',
number: 'el-input-number'
};
</script>
<template>
<form v-for="(field, key) in schema.properties" :key="key">
<component
:is="componentMap[field.type]"
v-model="formData[key]"
:min="field.minimum"
/>
</form>
</template>
性能考量
- SSR 水合性能 :
- Markdown 方案 AST 解析耗时约 5 -15ms(取决于内容长度)
-
生成式 UI 的 JSON 解析 + 组件实例化耗时约 20-40ms
-
虚拟滚动优化 :
- 使用 react-window/vue-virtual-scroller 实现
- 关键配置:
itemSize: 80, // 每项预估高度 overscan: 5 // 预渲染数量
避坑指南
XSS 防护
- 输入过滤 :
DOMPurify.sanitize(markdownContent) - CSP 策略 :
Content-Security-Policy: default-src 'self' - 输出编码 :
document.createTextNode(rawContent)
移动端优化
- 使用 CSS containment 限制重绘范围
- 对于长对话采用分页加载(每页 50-100 条)
- 避免在滚动容器中使用 box-shadow
状态管理
- 全局存储模式 :适用于简单对话流
- 会话上下文模式 :每个对话独立状态树
- 事件溯源模式 :通过事件重建状态(适合 undo/redo)
延伸思考
在实时协作编辑场景下,可以:
1. 使用 Markdown 作为基础存储格式
2. 对需要交互的部分采用生成式 UI 补丁
3. 通过 OT 算法同步两种数据结构
欢迎在示例仓库提交你的实现方案:
github.com/ai-dialog-impl
正文完
发表至: 前端开发
近两天内
