用 TinyRobot Bubble 组件打造灵活强大的 AI 对话气泡
引言:为什么 AI 对话界面需要灵活的气泡组件?
消息气泡?在 AI 对话应用中,它绝不仅仅是一个“框里放文字”的简单 UI 组件。随着大语言模型能力日益增强,AI 回复可能包含流式输出文本、Markdown 格式、代码块、图片、工具调用结果、推理过程等多种内容类型。与此同时,对话界面还需处理消息分组、角色区分、加载状态、交互式内容等复杂需求。

如果每次都需要从零实现,开发者很容易陷入 UI 适配与状态管理的困境。TinyRobot Bubble 组件正是为解决这些痛点而生——它提供了一套基于渲染器架构的声明式气泡系统,让您用极少的代码即可构建专业级的 AI 对话界面。
核心能力一览
| 特性 | 说明 |
|---|---|
| 多类型消息展示 | 支持文本、图片、Markdown、代码等多种内容格式 |
| 流式输出 | 响应式 content,天然支持打字机效果 |
| 消息分组 | 提供连续、分割、自定义三种分组策略 |
| 渲染器架构 | Box 渲染器 + Content 渲染器,完全可扩展 |
| 状态管理 | 内置 state 属性与 state-change 事件机制 |
| 丰富插槽 | 支持 prefix、suffix、after、content-footer 等插槽 |
| CSS 变量 | 50+ 变量覆盖气泡各子模块样式,方便快速定制 |
代码示例
1. 基础气泡使用
最基础的气泡只需传入一个 content 属性。通过 CSS 变量可快速调整外观样式。
复制代码
TrBubble 是气泡组件的基础入口。将字符串作为 content 传入后,组件会自动使用内置的 BubbleRenderers.Text 渲染器展示文字。通过 --tr-bubble-box-bg 设置气泡背景色,--tr-bubble-text-font-size 控制文字大小,轻松实现自定义样式。
2. 流式文本——AI 回复的打字机效果
AI 回复通常是逐字生成的。Bubble 的 content 是响应式的——动态追加内容即可实现流式输出效果。
复制代码
关键点:content 被定义为 ref,每次追加字符都会触发重新渲染,Bubble 内部会自动高效更新显示内容,无需额外配置。
3. 头像和位置
placement 属性控制气泡在对话流中的对齐方向,a vatar 接受 VNode 或组件来自定义头像图标。
复制代码
placement="end" 让气泡靠右对齐(通常用于用户消息),placement="start" 靠左对齐(通常用于 AI 回复)。a vatar 通过 Vue 的 h() 函数渲染 SVG 图标组件,灵活且可定制。
4. BubbleList + roleConfigs:批量消息管理
单条气泡适合演示,真实应用场景推荐使用 TrBubbleList 渲染消息列表,并通过 roleConfigs 统一配置每个角色的外观。
复制代码
BubbleList 中每个消息对象包含 role 和 content 字段。roleConfigs 根据 role 名称映射配置,BubbleRoleConfig 支持配置 a vatar、placement、shape、hidden 等属性,方便统一管理不同角色的消息样式。
分组策略:通过 group-strategy 属性控制消息分组方式:
'consecutive'(连续分组):将连续相同角色的消息合并为一组,适合追求最小化视觉干扰的对话流'divider'(分割分组,默认):以dividerRole(默认为'user')为分割线,每条分割角色消息单独成组- 自定义函数:
(messages, dividerRole?) => BubbleMessageGroup[],完全掌控分组逻辑
复制代码
5. Markdown 渲染
AI 回复通常包含丰富的格式化内容。Bubble 内置了 BubbleRenderers.Markdown 渲染器,使用时需安装 markdown-it 和 dompurify:
复制代码pnpm add markdown-it dompurify
复制代码
通过设置 fallback-content-renderer 为 Markdown 渲染器,当内置渲染器无法匹配内容类型时自动降级。若希望全局启用 Markdown 渲染,可使用 BubbleProvider(详见下文渲染器架构部分)。
6. 自定义 Content 渲染器
当内置渲染器无法满足特定需求时(如自定义代码块、图表、特殊卡片),可以实现自定义 Content 渲染器。
复制代码
自定义 Content 渲染器接收 BubbleContentRendererProps(包含 message 和 contentIndex)。推荐使用 useMessageContent(props) 辅助函数获取当前内容项——它会根据 contentIndex 自动从数组中提取正确的元素,简化开发流程。
7. 状态管理与交互
Bubble 的 state 属性用于存储 UI 相关数据(不影响消息内容),通过 state-change 事件实现状态更新。非常适合实现展开/收起、点赞、复制等交互功能。
复制代码
详细信息:该消息包含扩展内容,可用于展示补充说明。
state-change 事件回调的参数结构为 { key, value, messageIndex, contentIndex },其中 messageIndex 和 contentIndex 在 BubbleList 中用于精确定位具体消息,便于批量管理。
渲染器架构深度解析
TinyRobot Bubble 的核心设计是渲染器架构——将“容器样式”与“内容渲染”解耦为两种独立的渲染器,极大提升了扩展性。
Box 渲染器 vs Content 渲染器
| 类型 | 职责 | Props | 典型场景 |
|---|---|---|---|
| Box 渲染器 | 渲染气泡外层容器,控制整体样式与布局 | placement, shape | 自定义气泡形状、背景色、阴影等外观 |
| Content 渲染器 | 渲染消息的具体内容 | message, contentIndex | 文本、图片、Markdown、代码块等多样化内容 |
每种渲染器都通过匹配规则(Match)决定何时激活。匹配规则包含 find 函数和 priority 优先级属性。
渲染器匹配机制
匹配过程如下:
- 按
priority从小到大排序所有规则(数值越小优先级越高) - 依次执行每个规则的
find函数,找到第一个返回true的规则 - 使用该规则对应的渲染器
- 如果没有匹配到任何规则,则使用 fallback 渲染器
优先级常量(通过 BubbleRendererMatchPriority 访问):
| 常量 | 数值 | 触发条件示例 |
|---|---|---|
LOADING | -1 | message.loading === true |
NORMAL | 0 | 默认优先级,常规规则 |
CONTENT | 10 | content.type === 'image_url' |
ROLE | 20 | message.role === 'tool' |
配置层级
渲染器可在三个层级进行配置,优先级从高到低:
- Prop 级别:直接在
TrBubble上设置fallback-box-renderer/fallback-content-renderer,仅对当前组件生效 - Provider 级别:通过
BubbleProvider的box-renderer-matches/content-renderer-matches配置,在整个组件树中生效 - Default 级别:内置的默认渲染器
通过 BubbleProvider 全局配置渲染器
复制代码
内置渲染器一览
通过 BubbleRenderers 访问:
| 渲染器 | 类型 | 说明 |
|---|---|---|
BubbleRenderers.Box | Box | 默认气泡容器渲染器 |
BubbleRenderers.Text | Content | 文本内容渲染器(默认) |
BubbleRenderers.Image | Content | 图片渲染器(type: 'image_url') |
BubbleRenderers.Markdown | Content | Markdown 渲染器 |
BubbleRenderers.Loading | Content | 加载动画渲染器 |
BubbleRenderers.Reasoning | Content | 推理过程展示渲染器 |
BubbleRenderers.Tool | Content | 单个工具调用渲染器 |
BubbleRenderers.Tools | Content | 工具调用列表渲染器 |
BubbleRenderers.ToolRole | Content | 工具角色消息渲染器 |
推理内容(Reasoning)用于展示 AI 的思考过程,通过 reasoning_content 属性传入:
复制代码
CSS 变量定制
TinyRobot Bubble 提供了 50+ 个 CSS 变量,覆盖从根容器到各子模块的样式。以下是核心变量的分类概览:
Bubble 根元素
| 变量 | 说明 | 默认值 |
|---|---|---|
--tr-bubble-gap | 头像与内容之间的间距 | 8px |
--tr-bubble-max-width | 气泡最大宽度 | 80% |
--tr-bubble-min-width | 气泡最小宽度 | - |
Box 容器
| 变量 | 说明 |
|---|---|
--tr-bubble-box-bg | 背景色 |
--tr-bubble-box-padding | 内边距 |
--tr-bubble-box-border-radius | 圆角大小 |
--tr-bubble-box-shadow | 阴影效果 |
--tr-bubble-box-border | 边框样式 |
--tr-bubble-box-shape-rounded-radius | rounded 形状的圆角 |
--tr-bubble-box-shape-corner-radius | corner 形状的特定角圆角 |
文本
| 变量 | 说明 |
|---|---|
--tr-bubble-text-color | 文字颜色 |
--tr-bubble-text-font-size | 字号大小 |
--tr-bubble-text-line-height | 行高 |
加载状态
| 变量 | 说明 |
|---|---|
--tr-bubble-loading-color | 加载图标颜色 |
--tr-bubble-loading-size | 加载图标尺寸 |
图片
| 变量 | 说明 |
|---|---|
--tr-bubble-image-max-width | 图片最大宽度 |
--tr-bubble-image-max-height | 图片最大高度 |
--tr-bubble-image-border-radius | 图片圆角 |
推理内容
| 变量 | 说明 |
|---|---|
--tr-bubble-reasoning-max-height | 推理区域最大高度 |
--tr-bubble-reasoning-side-border-width | 左侧边线宽度 |
--tr-bubble-reasoning-side-border-color | 左侧边线颜色 |
BubbleList 容器
| 变量 | 说明 |
|---|---|
--tr-bubble-list-gap | 气泡之间的间距 |
--tr-bubble-list-padding | 容器内边距 |
所有变量均可通过 style 属性或 CSS 类轻松覆盖:
复制代码:deep([data-role='user']) {
--tr-bubble-box-bg: #e3f2fd;
--tr-bubble-text-font-size: 15px;
--tr-bubble-box-shape-rounded-radius: 16px;
}:deep([data-role='ai']) {
--tr-bubble-box-bg: #ffffff;
--tr-bubble-box-border: 1px solid #e8e8e8;
}
总结
TinyRobot Bubble 组件凭借渲染器架构、消息分组、流式支持以及灵活的 CSS 变量,为 AI 对话界面提供了完整的解决方案。其设计哲学是“约定优于配置”——默认行为已足够好用,同时每个环节都开放了扩展点:
- 需要自定义渲染逻辑?实现 Content 渲染器即可
- 需要改变气泡形态?实现 Box 渲染器
- 需要简单的样式调整?覆盖 CSS 变量
- 需要在全局统一渲染策略?使用 BubbleProvider
从简单的文本气泡到复杂的工具调用展示,从单条消息到分组列表,Bubble 组件能够在各种复杂度下保持一致且流畅的使用体验。
OpenTiny NEXT 是一套企业智能前端开发解决方案,以生成式 UI 和 WebMCP 两大核心技术为基础,对现有传统的 TinyVue 组件库、TinyEngine 低代码引擎等产品进行智能化升级,构建出面向 Agent 应用的前端 NEXT-SDKs、AI Extension、TinyRobot 智能助手、GenUI 等新产品,加速企业应用的智能化改造,实现 AI 理解用户意图并自主完成任务。
