Layout 性能
Layout 阶段负责确定每个 RenderObject 的尺寸和位置。它是大文档、大表格和复杂工作台中最容易被误用的阶段。
基本规则
- layout 只处理尺寸和位置,不做业务请求。
- layout 不应触发外部业务回调。
- layout 不应无条件调用
setItems、setData或重建子树。 - setter 必须做相等判断,避免相同值反复
markNeedsLayout。 - 大数据组件 layout 只计算可视窗口需要的信息。
常见反模式
在 layout 中写入同样数据
如果 layout 每次都调用子组件的 setItems(items),即使 items 内容没变,也可能导致子组件继续 markNeedsLayout,形成持续布局。
推荐增加签名或浅比较:
let lastSignature = '' function syncItems(items: readonly string[]): void { const signature = items.join('|') if (signature === lastSignature) return lastSignature = signature state.items = [...items]}
无界约束下使用弹性填充
滚动内容常常在主轴上是无界的。无界约束下不能依赖 flex 分配剩余高度,应按自然高度布局。
resize 时全量测量
窗口缩放会高频触发布局。大文档、大树、大表格不能在每次 resize 时全量测量所有节点。
诊断方法
- 打开 Runtime Diagnostics。
- 查看 layout request 的 target。
- 查看调用栈是否来自组件 setter 或 layout 内部同步。
- 检查是否同一 target 持续请求 layout。
- 在组件中增加 debugState 或签名,确认数据是否真的变化。
大文档策略
分页文档应区分:
- 当前编辑节点局部排版。
- 当前页局部排版。
- 后续页异步或分批排版。
- 全文重新分页。
不是所有文本变化都需要全量 reflow。关键判断是:当前段落、当前页和后续页的高度是否变化。