Skip to content

第 10 章:跨平台滚动、布局与 Slot 一致性 ​

1. 共享的不是 View 类,而是不变量 ​

Android 和 iOS 没有强行使用相同的原生 widget;它们共享以下 behavioral contract:

行为AndroidiOS
snapshot decodeJSONObject + parser executorJSONDecoder + parsing queue
owner changereset pager/page viewport/refreshreset pager/page viewport/refresh
tabViewPager2paging UIScrollView
body listRecyclerViewUITableView
handoff无 page,发 intent无 page,发 intent
slot hostViewGroup reparentUIView reparent
owner mismatchownerAuthorized=false,吞触摸hidden/accessibility hidden,Surface hitTest 拒绝
refreshrequest id + completeRefreshrequest id + completeRefresh

2. Header collapse offset 是共同语言 ​

用户看到的是一个页面,但实现中 header、tabs 和 body 可能由不同滚动容器承载。两端都需要一个抽象量:collapseOffset。

如果切 tab 时不把 offset 同步给目标页,用户会看到:当前页已经折叠,下一页却从 expanded header 开始;slot host 也会瞬间换高度。这是状态连续性 bug,而不只是动画问题。

3. Slot layout 的共同流程 ​

这个流程必须可重复、幂等:同一个 slot 可能因为列表复用、tab attach、dynamic type 或 owner 变化被多次 layout。代码使用“当前 parent 是否为 host”“当前尺寸是否一致”“mounted keys 是否变化”等检查减少无意义 reparent。

4. React slot 的交互模式 ​

wrapper 为 slot 设置两层 pointerEvents:

tsx
const interactive = slot.interaction === 'tap';
<HomeContainerSlot pointerEvents={interactive ? 'auto' : 'none'}>
  <View pointerEvents={interactive ? 'auto' : 'none'}>{slot.content}</View>
</HomeContainerSlot>

这表达了一个重要分工:

  • interaction: none 的 slot 仍可作为视觉内容挂载,但不能截获 native scroll/tap;
  • interaction: tap 允许 React 内容响应,比如账号选择、余额刷新、空状态按钮;
  • native engine 自己的 action row、tabs、list item 仍然通过 native intent 产生事件。

5. 背景色优先级 ​

resolveHomeContainerBackgroundColor 规定:snapshot theme 的 background 优先于 slot 提供的 fallback,只有两者都没有时才用白色。这样在 state 尚未到达、React slot 已到达时仍有视觉背景;一旦 authoritative snapshot 到达,slot 不会覆盖主题。

6. 跨平台调试方法 ​

推荐按三层打点,而不是只截图:

  1. JS:记录 snapshot 的 owner、selectedTab、tab destination、slot keys;
  2. bridge:记录 state decode error、intent JSON、requestId;
  3. native:记录 page attach/detach、collapse offset、slot host size、owner authorization。

工程里已有 debugOverlayEnabled,Android 用洋红色 border/background,iOS 用 border;它是检查 Surface bounds 和 engine 实际占位的低成本工具。

基于 app-monorepo 2026-07-31 源码快照整理 · 非官方文档