界面状态与大数据
界面上的节点只是数据状态的一扇窗口。输入、请求、选择、编辑历史与可见行各有不同身份和寿命;把它们都塞进当前 DOM,就会在乱序响应、排序、虚拟卸载或撤销分支时失去用户意图。
核心模型
界面上的节点只是数据状态的一扇窗口。输入、请求、选择、编辑历史与可见行各有不同身份和寿命;把它们都塞进当前 DOM,就会在乱序响应、排序、虚拟卸载或撤销分支时失去用户意图。
原理与机制
输入不等于已提交查询
联想框至少区分输入值、组合输入状态、提交查询、候选、高亮和请求状态。中文 composition 期间通常暂停远程查询,结束后按策略触发;防抖只减少频率。每轮请求取得单调编号并取消旧工作,结果、错误和 loading 都需归属校验,A→B→A 不能只比较文字。空输入清空候选,失败保留可理解的重试入口;缓存键带语言及权限作用域,容量有界。这样输入反馈可以立即发生,而结果更新遵循独立的一致性规则。
可访问交互必须与实际状态一致
combobox 的展开状态、受控 listbox 和活动选项并非装饰属性。上下键移动、Enter 选择、Escape 收起及焦点保持都要定义;aria-activedescendant 指向的选项必须真的存在。候选尚未到达或虚拟行被卸载时,不能保留悬空引用,也不能把焦点悄悄交给 body。按角色定位的自动化检查再配合读屏、中文输入和放大验证,才能同时证明“正确选择”和“用户知道选了谁”。
把查询规模与渲染规模分别收敛
十万条数据先区分下载、筛选、排序、组件更新和布局瓶颈。服务端游标分页减少传输与计算,虚拟化减少 DOM,两者可以组合,却不能互相替代。定高列表将像素映射到左闭右开的索引窗口,再加少量 overscan;可变高度需测量缓存及累计偏移。上方行变高时保存顶部锚点行 ID 与行内偏移,重新求锚点位置并补偿,单存 scrollTop 无法维持同一阅读位置。
排序与选择依赖稳定的业务身份
分数为空应明确用 null,不以真假判断,0 仍是有效分数。多字段比较先处理缺失,再比较分数、指定 locale 的姓名;Collator 复用,比较器返回有符号数。现代稳定排序只保证当前输入中等值项的相对顺序,跨页仍需服务端统一排序和唯一 ID 兜底。编辑草稿、选择与校验结果以行 ID 存在数据层,不能随窗口卸载消失;跨页全选要说清是已加载行还是当前筛选全集。
撤销记录的是事务,而不是网络重播
历史可用 past、present、future 三组不可变快照表达,撤销和重做只移动快照;撤销后新编辑清空 future,因为形成了新分支。对象若原地修改,所有引用它的历史也会变,须使用不可变更新、结构共享或补丁。拖拽从起点到终点可合为一个事务,中间移动仅预览,取消回到起点;不应把100次 move 都塞进历史再猜着删除。远端保存的撤销是新业务操作,需要权限、版本和冲突处理,不能直接重发旧请求。
最小示例
javascript结果窗口为 [1,8),offset=20,总高2000;实际可见从索引2(第3行)开始,前后各多留一行。渲染行从 slice(start,end) 取,外层提供总占位高度。公式 O(1),渲染成本取决于窗口大小,不能直接套到折叠或可变行高。
核验:Node v24.19.0:标准窗口及零行边界断言通过;未运行浏览器滚动、动态行高或辅助技术测试。
边界与取舍
边界
- 虚拟化后浏览器查找、打印和读屏不一定能访问未渲染内容,需要对应产品路径。
- 原生稳定排序不保证不同语言环境和服务端排序一致;前端页内排序不能形成跨页全局有序。
- 撤销本地快照不等于撤销远端副作用;使用共享可变对象会让历史一起被修改。
取舍
- overscan 增大减少快速滚动空白,却增加渲染与内存;按设备和滚动行为测量。
- 快照简单易调试,但大文档成本高;补丁和结构共享更省空间,恢复与版本兼容更复杂。
口述示范
我会先给输入、请求、行记录和历史事务分配稳定身份。查询限制数据量,虚拟化限制 DOM,草稿和焦点策略跨卸载保留;排序、撤销及可访问性都按用户可见契约验收。
章节练习
参考来源与核验边界
- WAI-ARIA APG:Combobox · 核验 2026-10-04
- web.dev:Virtualize Large Lists · 核验 2026-10-04
- MDN:Intl.Collator · 核验 2026-10-04
- React:Updating Objects in State · 核验 2026-10-04
2026-10-04 核验;引用长列表文章用于窗口化原理,不将其历史版本组件 API 当作当前 react-window API。超大像素高度还须考虑浏览器限制。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。