介绍
聊天场景是网页中非常常见的情况,但你有注意过聊天的滚动条反转、向上滚动加载要怎么实现吗?下面我将介绍这种场景下的基础解决方案。
要点
向下无限滚动加载功能
在页面向下滚动无限加载的功能非常常见,且有非常多的库支持该功能,如element、ahooks都有相应的功能。其原理大致分为两种方案:
- 通过scroll事件获取HTML元素的
scrollTop
、scrollHeight
与clientHeight
属性做计算,得出当前位置是否应触发加载事件。 - 使用
IntersectionObserver
方法监听底部元素是否在视口内。但IntersectionObserver
内部使用了requestIdleCallback
降低方法优先度,也导致如果有其他占用线程的工作或高频触发滚动,IntersectionObserver
无法精准触发事件。
滚动条反转
在实现了向下无限滚动加载的功能后,我们只需要将顺序调转,让用户从下往上滚动就可以实现我们的目标了。但设想一下,如果我们直接在顶部拼接数据,而滚动条是基于scrollTop
的位置固定的,也就是当数据渲染出来后,用户的感受是页面跳动到最新一页的顶部。下面介绍两种解决方案:
- 常见的方案类似于iScroll库的实现方案。在页面初始时,设置scrollTop 为一个极大值,将页面定位至底部,页面向上滚动加载更多数据时,将scrollTop设置为当前展示的数据位置。这个方法在小程序由于小程序双线程的原因上会遇到页面跳动的问题。
- 另一个方案需要结合CSS。首先将列表容器旋转180°,这样新消息就会在上方,我们滚动到顶部的时候可以触发加载更多数据,滚动条也不会跳动。然后我们再将聊天内容也进行180°旋转,这样显示上就不会有问题了。但是滚动条的位置靠左与滚动的方向是错误的,当使用滚动轴向下滚动时,页面会向上滚动。首先解决滚动轴靠左的问题:我们在容器和内容分别加上
direction: rtl;
和direction: ltr;
。而滚动轴方向的问题就需要监听滚动轴事件并将滚动效果反转。
方案2图例:
这两个方案除了实现上的不同,数据的存储顺序也是不同的。第一种方案需要对单页数据进行反转才能实现从上到下、从新到旧,而第二种方案的数据可以保持从新到旧即可。