Skip to content

实践范例

所谓实践范例,就是用 Microsoft.UI.Reactor(Reactor)原语做的一小段组合,用来解决某个 真实的 UI 问题 —— 登录、主从视图、设置、分页列表、模态确认、多步表单、 带建议的搜索、命令面板、拖拽重排。这里收录的并不是完整的应用; 每个范例都是一个展示该模式的单一界面,并且都附带一个可以克隆并改造的 小型文档应用。

范例 展示的内容
登录 逐键校验、由 UseMutation 持有的提交状态、错误展示。
主从视图 由列表与记录驱动的双窗格布局。
设置页 Toggle / ComboBox / Slider 逐键使用 UsePersisted
分页列表 带空/加载/错误状态与「加载更多」哨兵的 UseInfiniteResource
模态对话框 带遮罩与条件渲染的确认模式。
多步表单 带逐步校验的向导式导航。
带建议的搜索 UseMemo 针对静态目录过滤出的建议列表。
命令面板 由键盘加速器打开、内含已过滤命令列表的叠加层。
拖拽重排 保持身份的键控列表重排,并提供键盘操作路径。
class RecipesIndexApp : Component
{
    public override Element Render() => VStack(12,
        Heading("Recipes"),
        TextBlock("Real-world compositions made of Reactor primitives.")
            .Opacity(0.7),
        VStack(8,
            HStack(8,
                Tile("Login", "Validation + async submit"),
                Tile("Master-detail", "Selection-driven layout"),
                Tile("Settings", "Persisted preferences")),
            HStack(8,
                Tile("Paginated list", "Loading + empty + error states"),
                Tile("Modal dialog", "Scrim + confirmation flow"),
                Tile("Multi-step form", "Wizard validation")),
            HStack(8,
                Tile("Search", "Memoized suggestions"),
                Tile("Command palette", "Keyboard-opened overlay"),
                Tile("Drag-reorder", "Keyed list reordering"))
        )
    ).Padding(20);

    private static Element Tile(string title, string sub) => VStack(4,
        TextBlock(title).Bold(),
        TextBlock(sub).Opacity(0.6)
    ).Padding(12);
}

实践范例图库预览

这个图库所用的原语与每个范例页都相同 —— 用 VStack 做纵向布局、用 TextBlock 写说明文字、 用 HStack 排出每一行瓦片。那个瓦片辅助方法是私有的静态方法,而不是组件, 因此它没有 Hook 作用域:

private static Element Tile(string title, string sub) => VStack(4,
    TextBlock(title).Bold(),
    TextBlock(sub).Opacity(0.6)
).Padding(12);

本目录下的每一页都遵循同样的形态:

// 本目录下每个范例页都会从 docs/_pipeline/apps/recipe-<name>/ 引入一个小小的
// 专用文档应用。范例模板会渲染三个片段标记(state / shape / render),
// 外加一张供上方图库缩略图使用的截图。
class GalleryShape : Component
{
    public override Element Render() => TextBlock("see docs/_pipeline/apps/recipe-*");
}

如何阅读一个实践范例

每个范例的形态都相同:

  1. 一段该范例的可运行代码片段,取自 docs/_pipeline/apps/recipe-<name>/ 下真实的 文档应用。
  2. 一张该范例运行时的截图,由文档流水线工具采集。
  3. 一两段走读说明,点出该范例组合了哪些原语,以及支撑这个模式的 设计决策。

这些范例倾向于组合既有工厂方法 —— 每个范例都不自定义 Component。若想把某个范例用到你的应用里,复制片段并把目录数据换成你自己的即可。

参考

原语 使用者
UseState 大多数范例。
UsePersisted 设置页
UseMemo 搜索
UseMutation 登录 —— 异步提交、进行中、错误。
UseInfiniteResource 分页列表
条件渲染 模态对话框命令面板
双窗格 HStack 主从视图
键控子项 拖拽重排

提示

先找现成的范例,再动手写代码。 大多数「我需要一个设置页」或「我们需要一个登录表单」的需求, 都能由这些模式之一满足。范例就是那套组合;自己发明一套的代价, 就是调试它的代价。

范例是起点,不是成品。 把片段放进你的应用再改造它 —— 数据、样式令牌、校验 规则。这里真正有价值的是组合的形态。

在伸手找范例之前,先搜一遍控件目录。 由一个控件就能解决的问题(表单数据系统)不需要范例;范例是为那些横跨多个控件与 Hook 的 形态而存在的。

后续阅读

  • 控件 —— 上一篇:这些范例所组合的工厂方法目录。
  • 表单 —— 表单密集型的范例从那里开始。
  • 异步资源 —— 登录与分页列表示例背后的机制。
  • 持久化 —— 设置页示例背后的机制。
  • 命令 —— 支撑命令面板示例的机制。
  • 导航 —— 横跨多个界面的范例依赖它。