02 · 核心概念¶
FlowUI 用三句话就能说明白。学完本页,后面各章都是在展开这三句话。
三句话¶
- Model + 消息 + Update 管业务数据;View 只读 Model,用
send表达意图。 - Style 管这个盒子的尺寸与外观;布局容器 管孩子们怎么排列。
- 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 链式配置 |
| When | 按交互/语义状态叠样式(Hover、Pressed…) |
| Part | 复合控件内部零件(Track、Thumb、Label…) |
| Key | 字符串身份;有状态控件必须显式提供 |
| Host | 统一单盒外壳绘制;Box / LayoutInteractiveResolvedStyle |
| 受控 / 非受控 | 值或 open 是否由 Model 持有 |
| Action | 菜单/快捷键配方;与异步 Cmd 不是一回事 |
构造函数与类型名¶
Go 不允许函数与类型同名,因此:
btn := ui.Button("save", ui.Text("保存")) // 构造函数
// 类型是 ButtonWidget,方法在类型上:
btn = btn.Variant(ui.ButtonPrimary).OnClick(func() { ... })
go doc / IDE 补全看 ButtonWidget、InputWidget 等方法集。
Context 是什么¶
*ui.Context 是每个窗口的帧与交互服务,不是第二个 Model:
- 可读:
Theme()、Language()、WindowState() - 焦点:
RequestFocus、FocusVisible - 自定义控件:
UseState(仅瞬态交互,不是业务状态)
业务字段请放进你的 Model。
与 Gio 的关系¶
FlowUI 建立在 Gio 之上。日常应用只需 ui 包;路径 C 画布自绘时才会直接接触 Gio 的 layout / op。
产品 API 不按 Gio 细节组织,按 MVU + Style + 布局来学即可。