无限滚动列表的位置恢复依赖已加载数据量,返回过深会触发重新加载
别名: 无限滚动恢复加载 · virtual list window · 返回过深重载 · restore fetch depth
概念解释
无限列表没有页码,位置活在「已经取到的那一段窗口」里。离开时窗口可能有几百条,回来时组件从第一页重建,锚点的 id 还不在内存里。恢复依赖已加载量:要把人放回原来那条,必须先重新取得从起点到该条之间(或直接按游标取到该窗口)的数据。走得越深,这一笔加载越重,人会先看到顶部或骨架,以为恢复失败。虚拟列表只渲染视口附近的 DOM,问题同样是数据窗口,不是 DOM 节点数。
机制
分页列表的「第 3 页」是一条可再请求的坐标。无限列表的坐标是游标或偏移,加上当时窗口里的条目。窗口被卸载后,只记得 id 不够——服务端可能不提供「任意 id 的周围一页」,只能从最新端一页页往下补,直到撞上该 id。深度与补齐时间几乎线性,弱网下会到十几秒。产品若在补齐完成前就交出可交互的第一页,人开始往下滚,补齐完成时又被拽回锚点,等于二次打断。
虚拟化还带来高度未知:未测量过的项用估计高度占位,补齐后总高度跳变,滚到「估计位置」会对不准真项。所以过深恢复有三层成本:网络取回窗口、布局测量、避免在完成前露出错误的第一屏。没有这三层,无限列表的 scroll restoration 只在浅处碰巧成功。
怎么研究
让人滚到不同深度(一屏、十屏、五十屏)进详情再返回,比较窗口缓存、按游标直接取周围页、从顶重放到锚点。
- 自变量:深度、是否保留离开时的数据窗口、弱网。
- 因变量:锚点出现在视口内的时间、是否先出现顶部、补齐过程中的二次跳动。
- 方法论注意点:实验室 Wi-Fi 会掩盖五十屏的成本。必须限速。不要只用「最后是否在那条」当成功——先闪顶部再跳,在体验上仍是失败。冷启动与会话内返回要分开,前者窗口一定没了。
边界
有「加载更多」按钮的有限分页不是这条:页码本身可请求。深度浅、窗口本来就在第一页里,没有重载问题。服务端提供 around=id 一类接口时,成本与深度脱钩,这条的线性代价不成立,但仍要避免先画顶。用户主动下拉刷新,是放弃当前窗口。
怎么落地
- 离开无限列表时缓存数据窗口和锚点 id;会话内返回先复用窗口,不要从第一页重放。
- 窗口已丢时用「围绕 id 取一页」的接口;没有这种接口就在后台补齐,期间用骨架占住原视口,禁止交出可滚动的第一页。
- 过深且无法在短时间内取回时,落到最近可取的窗口并说明「内容需重新加载」,而不是假装还在原来那条。
- 验证:滚过至少十屏,进详情,返回。锚点应在视口内且中间没有可交互的顶部。杀掉进程再走一次,允许骨架,仍不准先让人滚动第一页。限速 3G 再测十屏以上,记录是否出现二次跳动。