虚拟表格滚动后,编辑状态应该保存在哪里
从 ERP 大表格场景分析行节点复用:用稳定行标识管理草稿、校验和焦点,避免滚动、排序与刷新让编辑内容串行或丢失。
延伸分析 · 从项目场景展开的原理与方案讨论。
- 虚拟列表
- 表格编辑
- 状态管理
- 稳定标识
关联项目:企业 ERP 管理系统。项目资料包含虚拟化表格应用。本文进一步分析可编辑虚拟表格的状态归属,不代表原项目采用了文中的全部设计。
行离开视口,业务状态不该随之消失
虚拟化只渲染可见区域附近的行,可以减少 DOM 数量。但用户正在编辑的记录即使滚出了屏幕,它的草稿、错误和保存结果仍然存在。
若把草稿仅放在单元格组件的局部状态中,组件卸载就可能丢失修改;如果节点被复用给另一条记录,又可能把上一行的输入带过去。优化渲染数量之后,还要重新划清状态生命周期。
记录身份不能跟着数组位置变化
排序和筛选会改变下标。应让记录 ID、列标识共同决定一个单元格的业务身份,例如 rowId + columnKey,而不是“当前第 5 行”。
虚拟化库也需要稳定标识才能关联测量和节点。TanStack Virtual 的 getItemKey 文档可以作为 API 设计参考;这里并不表示 ERP 项目使用了该库。
把编辑状态放在渲染窗口之外
可以按职责保存几份状态:
| 状态 | 建议身份 | 作用 |
|---|---|---|
| 服务端记录 | rowId | 最近确认的数据和版本 |
| 本地草稿 | rowId、columnKey | 尚未提交的输入 |
| 校验错误 | rowId、columnKey | 随滚动继续保留的反馈 |
| 活动单元格 | rowId、columnKey | 重新进入视口时恢复交互 |
单元格挂载后读取自己的草稿,输入时更新草稿容器。展示窗口变化只改变哪些控件存在,不直接决定哪些修改有效。
这不等于要把所有数据塞进全局 store。状态放在表格或编辑任务的生命周期内即可;离开页面是否保留,应由产品交互决定。
数据刷新不能无条件覆盖草稿
服务端刷新到来时,未编辑字段可以更新;已有草稿的字段需要保留用户输入,或者提示服务端值发生变化。保存时若要检测并发覆盖,需要后端提供版本校验等契约,前端的 dirty 标记本身不能防止丢失更新。
记录被删除、权限变化和保存失败也不应靠组件销毁“自动解决”。这些状态需要一个可见的处理入口,用户才能决定重试、放弃或重新读取。
焦点恢复也依赖记录身份
按键移动到尚未渲染的行时,先请求虚拟列表让目标进入渲染范围,等待节点可用后再聚焦。恢复任务必须验证目标仍是当前活动单元格,避免快速移动后旧任务抢回焦点。
不能长期保存一个 DOM 引用,假设它始终代表同一条记录。
滚动性能之外的验收
输入未保存内容,滚出视口再回来;随后排序、筛选、刷新和删除记录,确认草稿始终属于原记录。再覆盖异步校验返回、保存失败以及键盘导航。
虚拟化解决“同时渲染多少行”。编辑模型解决“每次修改属于谁、何时生效”。两者分开,才能兼顾性能与正确性。