Skip to content

组件与结构

A2UI 使用邻接列表模型表示组件层次结构。组件不是嵌套的 JSON 树,而是带有 ID 引用的扁平列表。

为什么使用扁平列表?

传统嵌套方法:

  • LLM 必须一次性生成完美的嵌套
  • 难以更新深层嵌套的组件
  • 难以增量流式传输

A2UI 邻接列表:

  • ✅ 扁平结构,LLM 易于生成
  • ✅ 增量发送组件
  • ✅ 通过 ID 更新任何组件
  • ✅ 清晰分离结构和数据

邻接列表模型

{
  "surfaceUpdate": {
    "components": [
      {"id": "root", "component": {"Column": {"children": {"explicitList": ["greeting", "buttons"]}}}},
      {"id": "greeting", "component": {"Text": {"text": {"literalString": "你好"}}}},
      {"id": "buttons", "component": {"Row": {"children": {"explicitList": ["cancel-btn", "ok-btn"]}}}},
      {"id": "cancel-btn", "component": {"Button": {"child": "cancel-text", "action": {"name": "cancel"}}}},
      {"id": "cancel-text", "component": {"Text": {"text": {"literalString": "取消"}}}},
      {"id": "ok-btn", "component": {"Button": {"child": "ok-text", "action": {"name": "ok"}}}},
      {"id": "ok-text", "component": {"Text": {"text": {"literalString": "确定"}}}}
    ]
  }
}

组件通过 ID 引用子元素,而不是通过嵌套。

组件基础

每个组件都有:

  1. ID:唯一标识符("welcome"
  2. Type(类型):组件类型(TextButtonCard
  3. Properties(属性):特定于该类型的配置
{"id": "welcome", "component": {"Text": {"text": {"literalString": "你好"}, "usageHint": "h1"}}}

标准目录

A2UI 定义了按用途组织的标准组件目录:

  • 布局:Row、Column、List - 排列其他组件
  • 显示:Text、Image、Icon、Video、Divider - 显示信息
  • 交互:Button、TextField、CheckBox、DateTimeInput、Slider - 用户输入
  • 容器:Card、Tabs、Modal - 分组和组织内容

有关完整的组件库和示例,请参见组件参考

静态与动态子元素

静态(explicitList - 固定的子 ID 列表:

{"children": {"explicitList": ["back-btn", "title", "menu-btn"]}}

动态(template - 从数据数组生成子元素:

{"children": {"template": {"dataBinding": "/items", "componentId": "item-template"}}}

对于 /items 中的每个项目,渲染 item-template。详见数据绑定

填充值

组件通过两种方式获取值:

  • 字面量 - 固定值:{"text": {"literalString": "欢迎"}}
  • 数据绑定 - 来自数据模型:{"text": {"path": "/user/name"}}

LLM 可以生成带有字面量值的组件,或将它们绑定到数据路径以获取动态内容。

组合界面

组件组合成界面(组件):

  1. LLM 通过 surfaceUpdate 生成组件定义
  2. LLM 通过 dataModelUpdate 填充数据
  3. LLM 通过 beginRendering 发出渲染信号
  4. 客户端将所有组件渲染为原生组件

界面是一个完整、连贯的 UI(表单、仪表板、聊天等)。

增量更新

  • 添加 - 发送带有新组件 ID 的新 surfaceUpdate
  • 更新 - 发送带有现有 ID 和新属性的 surfaceUpdate
  • 移除 - 更新父元素的 children 列表以排除已移除的 ID

扁平结构使所有更新都成为简单的基于 ID 的操作。

自定义组件

除了标准目录之外,客户端还可以为特定领域的需求定义自定义组件:

  • 如何:在你的渲染器中注册自定义组件类型
  • 什么:图表、地图、自定义可视化、专用组件
  • 安全性:自定义组件仍然是客户端可信目录的一部分

自定义组件从客户端的渲染器通告给 LLM。然后 LLM 可以在标准目录之外使用它们。

有关实现细节,请参见自定义组件指南

最佳实践

  1. 描述性 ID:使用 "user-profile-card" 而不是 "c1"
  2. 浅层次结构:避免深度嵌套
  3. 分离结构和内容:使用数据绑定,而不是字面量
  4. 使用模板重用:一个模板,通过动态子元素生成多个实例