Skip to content

数据绑定

数据绑定使用 JSON Pointer 路径 (RFC 6901) 将 UI 组件连接到应用程序状态。这使得 A2UI 能够高效地定义大型数据数组的布局,或在不从头重新生成的情况下显示更新的内容。

结构与状态

A2UI 分离了:

  1. UI 结构(组件):界面的外观
  2. 应用程序状态(数据模型):显示的数据

这实现了:响应式更新、数据驱动的 UI、可重用模板和双向绑定。

数据模型

每个表面都有一个保存状态的 JSON 对象:

{
  "user": {"name": "Alice", "email": "alice@example.com"},
  "cart": {
    "items": [{"name": "Widget", "price": 9.99, "quantity": 2}],
    "total": 19.98
  }
}

JSON 指针路径

语法:

  • /user/name - 对象属性
  • /cart/items/0 - 数组索引(从零开始)
  • /cart/items/0/price - 嵌套路径

示例:

{"user": {"name": "Alice"}, "items": ["Apple", "Banana"]}
  • /user/name"Alice"
  • /items/0"Apple"

字面量与路径值

字面量(固定):

{"id": "title", "component": {"Text": {"text": {"literalString": "Welcome"}}}}

数据绑定(响应式):

{"id": "username", "component": {"Text": {"text": {"path": "/user/name"}}}}

/user/name 从 "Alice" 变为 "Bob" 时,文本自动更新为 "Bob"。

响应式更新

绑定到数据路径的组件在数据更改时自动更新:

{"id": "status", "component": {"Text": {"text": {"path": "/order/status"}}}}

初始: /order/status = "Processing..." → 显示 "Processing..." 更新: 发送 dataModelUpdate 带有 status: "Shipped" → 显示 "Shipped"

无需更新组件——只需更新数据。

动态列表

使用模板渲染数组:

{
  "id": "product-list",
  "component": {
    "Column": {
      "children": {"template": {"dataBinding": "/products", "componentId": "product-card"}}
    }
  }
}

数据:

{"products": [{"name": "Widget", "price": 9.99}, {"name": "Gadget", "price": 19.99}]}

结果: 渲染两张卡片,每个产品一张。

作用域路径

在模板内部,路径作用于数组项:

{"id": "product-name", "component": {"Text": {"text": {"path": "/name"}}}}

对于 /products/0/name 解析为 /products/0/name → "Widget" 对于 /products/1/name 解析为 /products/1/name → "Gadget"

添加/移除项会自动更新渲染的组件。

输入绑定

交互式组件双向更新数据模型:

组件 示例 用户操作 数据更新
TextField {"text": {"path": "/form/name"}} 输入 "Alice" /form/name = "Alice"
CheckBox {"value": {"path": "/form/agreed"}} 勾选复选框 /form/agreed = true
MultipleChoice {"selections": {"path": "/form/country"}} 选择 "Canada" /form/country = ["ca"]

最佳实践

1. 使用粒度更新 - 仅更新更改的路径:

{"dataModelUpdate": {"path": "/user", "contents": [{"key": "name", "valueString": "Alice"}]}}

2. 按领域组织 - 对相关数据进行分组:

{"user": {...}, "cart": {...}, "ui": {...}}

3. 预计算显示值 - 代理在发送前格式化数据(货币、日期):

{"price": "$19.99"}  // 而非:{"price": 19.99}