外观
上拉加载和下拉刷新怎么做?
下拉刷新是在列表顶部把内容换成第一页。上拉加载是接近底部时请求下一页并追加。两者都要有进行中的锁,避免一次手势打出多次请求。
原理
底部用哨兵元素配合 IntersectionObserver,进入可视区域且还有下一页时请求。请求参数带页码或上一页的游标。游标比页码更能应对列表中间被插入新数据。见 可视区域。
返回的数据追加到已有列表。空页表示没有更多,卸掉哨兵或不再触发。失败时保留已有列表,并允许再试。
下拉刷新用触摸位移或浏览器的下拉能力。松手之后请求第一页,成功时替换列表而不是追加,并把滚动位置放回顶部。刷新进行中,底部加载先停掉。
长列表再配合虚拟列表,避免页数变多之后 DOM 无限增长。见 无限列表。
移动端的整页回弹和页面里的某个容器滚动是两回事。监听触摸时要确认触摸起点在这个容器里,并用样式禁止不该发生的浏览器默认下拉。
追问
页码和游标?
页码实现简单,数据有新增时可能重复或漏掉。时间线、消息用「比某 id 更旧的 n 条」这种游标更稳。
和无限滚动的差别?
上拉加载就是分页的无限滚动。下拉刷新是重新取最新一页。两个动作的数据策略相反:一个追加,一个替换。
易错点
- 没有锁,哨兵一直可见,连续请求每一页。
- 刷新失败却把列表清空了。
- 追加时用下标当
key,新的一页和旧的一页状态串了。