Skip to content

条件、列表与虚拟化 ​

结构指令改变 Blueprint subtree,而不是只切换绘制透明度。选择正确的指令可以避免无效 Entity 和无界内存。

x:If ​

xml
<x:If Condition="{bind Account.IsLoggedIn}">
  <Text Text="已登录" />
  <x:Else>
    <Button Text="登录" Command="{cmd Account.Login}" />
  </x:Else>
</x:If>

x:If 是运行时结构 Binding。分支变化会实例化/销毁对应 subtree,并遵守 generation-safe reconcile。

x:Switch ​

xml
<x:Switch Value="{bind Download.State}">
  <x:Case Value="Idle"><Text Text="等待" /></x:Case>
  <x:Case Value="Downloading"><Text Text="下载中" /></x:Case>
  <x:Default><Text Text="未知状态" /></x:Default>
</x:Switch>

状态互斥且超过两个分支时使用 Switch,比嵌套多层 If 更清楚。

x:For ​

小规模集合可以直接展开:

xml
<x:For Each="{bind RecentFiles}" As="file" Key="{file.Id}">
  <Text Text="{file.Name}" />
</x:For>

同一 collection version 内,Key 必须唯一且稳定。插入或重排后,Runtime 依靠 Key 保留 presentation identity。

VirtualList ​

xml
<VirtualList
  Items="{bind Mods}"
  Key="{item.Id}"
  EstimatedItemHeight="48"
  OverscanBefore="2"
  OverscanAfter="3">
  <Template As="item">
    <ModItem Mod="{item}" />
  </Template>
</VirtualList>

VirtualList 的核心 contract:

  • 逻辑项不等于 Entity;只为 viewport + overscan 建立 slot。
  • 滚动时优先保留仍在新窗口内的 slot,只重绑定进入窗口的 item。
  • Version 只在集合拓扑、Key 或可观察 binding 数据变化时递增。
  • offset/index 查询保持 O(log N);100,000 项不能导致逐帧 O(N) 扫描。
  • 变长项的实测 extent 按当前 source 的 Key 缓存;source refresh 会清理已消失 Key。

如何选择 ​

需求选择
两个互斥分支x:If + x:Else
多状态互斥分支x:Switch
少量、全部需要存在的项x:For
大量可滚动项VirtualList
平台/版本在构建时决定x:IfBuild,不是运行时 If

下一章:组件、模板与 Slot。