02 · 核心概念¶
FlowUI 用三句话就能说明白。学完本页,后面各章都是在展开这三句话。
三句话¶
- Model + 消息 + Update 管业务数据;View 只读 Model,用
send表达意图。 - Style 管这个盒子的尺寸与外观;布局容器 管孩子们怎么排列。
- Key 管跨帧身份;固定布局可使用自动 Key,动态内容需要稳定的业务 Key 或作用域。
副作用(网络、定时器、文件)用 Cmd / Subscription,不要在 View 里改 Model。
数据流¶
用户点击 / 键盘 / 订阅
│
▼
send(Msg)
│
▼
Update(*Model, Msg) ← 唯一改 Model 的地方
│
├── 可选返回 Cmd(异步副作用)
▼
View(ctx, Model, send) → Widget 树
│
▼
布局 · 绘制 · 交互
职责边界¶
| 放这里 | 不放这里 |
|---|---|
| Model:业务字段、表单值、列表数据 | 指针点击态、动画进度 |
| Update:根据 Msg 改 Model | 直接画 UI、阻塞网络 |
| View:读 Model,声明控件树 | 改 Model、开 goroutine 改状态 |
| Context:主题快照、焦点、交互槽 | 业务数据 |
| Style:宽高、padding、颜色、阴影 | flex 增长、兄弟间距(容器负责) |
| Key:跨帧保留 clickable / 动画 | 用渲染顺序当身份 |
术语表¶
| 术语 | 含义 |
|---|---|
| MVU | Model-View-Update;消息驱动 |
| Widget | 可布局节点;实现 Layout(ctx, gtx) |
| Send | 把消息投进队列,下一帧由 Update 处理 |
| Cmd | Update 返回的异步命令;独立 goroutine 执行 |
| Subscription | 按 Model 声明的长生命周期输入(定时器、流) |
| Style | 不可变的外观/盒模型声明;fluent 链式配置 |
| On / Rules | 按交互/语义状态叠样式(Hover、Pressed…) |
| Part | 复合控件内部零件(Track、Thumb、Label…) |
| Key | 跨帧身份;固定布局可自动生成,动态内容使用业务身份 |
| Host | 统一单盒外壳绘制;Box / layout.InteractiveResolved |
| 受控 / 非受控 | 值或 open 是否由 Model 持有 |
| Action | 菜单/快捷键配方;与异步 Cmd 不是一回事 |
构造函数与类型名¶
主构造函数统一使用 New,类型使用 Widget,两者在 Go 命名空间中互不冲突:
btn := button.New("保存") // 构造函数直接接收文本
// 类型是 button.Widget,方法在类型上:
btn = btn.Variant(button.Primary).OnClick(func() { ... })
go doc / IDE 补全看 button.Widget、input.Widget 等方法集。
自动 Key 与显式 Key¶
button.New、input.New 等构造函数为固定布局提供自动身份:
自动身份由组件类型、构造位置、所在 Key 作用域,以及同位置组件在本帧首次解析 Key 的顺序决定。每个窗口独立计数;提前创建组件和每帧重新创建组件遵循相同规则。显示文本不参与身份判断。
动态列表、共用构造辅助函数的条件性兄弟组件,以及会改变位置的组件,应显式设置业务 Key:
重复的整个子树可使用 layout.Key(item.ID, child) 建立稳定作用域。普通 Row、Column 不会自动建立 Key 作用域。table.New 等直接接收 Key 的构造函数使用调用者传入的身份。
没有构造标记的底层交互原语,在收到空 Key 时按状态类型和作用域内顺序生成回退身份。它适用于位置稳定的内部结构,不能替代业务身份。
改变显式 Key 会建立新的交互身份;同一作用域内两个组件复用同一个 Key 属于错误。Key 是运行时身份,不用于持久化。自动标记格式属于内部实现,应用 Key 不应使用其保留的零字节分隔标记 \x00@。
Context 是什么¶
*ui.Context 是每个窗口的帧与交互服务,不是第二个 Model:
- 可读:
Theme()、Language()、WindowState() - 焦点:
RequestFocus、FocusVisible - 自定义控件:
UseState(仅瞬态交互,不是业务状态)
业务字段请放进你的 Model。
与 Gio 的关系¶
FlowUI 建立在 Gio 之上。日常应用只需 ui 包;路径 C 画布自绘时才会直接接触 Gio 的 layout / op。
产品 API 不按 Gio 细节组织,按 MVU + Style + 布局来学即可。