AUP 的最小单位是 node。一个 tree 说明界面里有什么、它们如何嵌套、哪些数据或事件与它们相关;它不把浏览器 CSS、iOS view 或终端字符画当成协议事实。
当前 AUPNode 的核心字段是:
| 字段 | 作用 | 作者应保持的约束 |
|---|---|---|
id | tree 内稳定身份 | 在同一个 tree 中唯一;不要把可变显示文字当 id |
type | primitive、Web widget 或已注册 custom type | 先查 target 的支持范围 |
props | type 特有的静态属性 | 只使用该 type 已支持的键 |
children | 子 node | 只在容器语义允许时嵌套 |
src | 只读 AFS 数据绑定 | 表达读取,不表达写入权限 |
bind | 读写 AFS 绑定,常用于 input | 只在已授权、可写的路径上使用 |
state | 本地 UI 状态 | 不把它误认为持久业务数据 |
events | 用户交互的声明 | 由事件合同处理,而不是在 renderer 中暗藏业务逻辑 |
概念 tree 可以写成:
view (id: profile)
├── text (id: profile-title)
└── action (id: open-settings)这里 view 描述容器意图,text 与 action 描述内容和操作意图。某个设备怎样排版、按钮长什么样、是否需要降级,是 target 的呈现问题;作者不应依赖某一个 renderer 的偶然 CSS 来改变 tree 的含义。
primitive 与 Web widget
当前核心类型表定义 18 个跨设备 primitive,例如 view、text、media、input、action、table、chat、editor、canvas 与 afs-list。Web runtime 另外注册 Web-only widget,例如 frame、terminal、breadcrumb、pagination 与 tooltip。后者可以在 Web renderer 中有实现,但不等于跨设备 primitive,也不会自动出现在每个设备的 DeviceCaps.primitives 中。
未知或 custom type 不能仅凭“parser 接受”就宣称跨设备可用。为目标 renderer 写一份小例子,并在真实设备/浏览器中验收;需要降级时看设备能力与降级。
data 与 UI 状态分开
src 表达只读数据路径;bind 表达读写绑定。二者都只是 UI 与 AFS 路径之间的合同,不会自动授予读取或写入权限。state 则是 UI-local 状态,例如当前 tab、展开与否;输入验证状态也可能是 renderer 的瞬时状态,不应被当作 AFS 中的持久记录。
下一步阅读事件、状态与绑定,再决定一个操作应执行 AFS action、改变 tree,还是只做浏览器级导航。