自定义滚动条,手撸不等高虚拟列表

5,869 阅读2分钟

前言

虚拟列表分为两种情等高的情况和不等高的情况,前几天写了一篇自定义滚动条,手撸等高虚拟列表,对于不等高的情况也有所思考,跟等高的思路是一样的,不同的只是计算重要值的方式不一样。思路就不讲了,建议去看一下前面等高的思路。后面附上完整的代码

正文

还是先看看效果

动画22.gif

记录列表元素高度信息

不等高虚拟列表的难点就是我们无法知道元素实际的高度,导致我们无法知道应该滚动的距离,所以我们要记录列表元素高度信息,包括元素的实际高度和上下边界在实际列表高度中的距离

interface Sign {
  top: number,
  height: number,
  bottom: number
}
/** 标记*/
const [sign, setSign] = useState<Sign[]>([])

同时,我们也需要一个默认值来当做元素还未渲染时的高度。

code.png

我们通过这个标记,列表的实际高度其实已经知道了

code.png

更新列表元素高度信息

当我们获取到渲染元素时,要去更新我们记录的元素高度信息。

对于更新渲染部分的元素高度信息,没什么好办法,只能乖乖走循环一个一个去更新。 但是要知道在记录的元素高度信息列表中一个元素高度的改变,那么这个元素之后的所有元素高度信息的top和bottom都会改变,我们都要去更新,这边我们可以小小的优化一下,不是改变一个元素信息就去循环更新剩下的元素高度信息,而是计算整个实际渲染部分与记录部分的高度总差值然后再统一的更新

code.png

寻找当前渲染元素开始下标

在等高的情况中我们可以通过计算算出下标

  • 当前列表开始渲染下标 = Math.floor(内容实际滚动距离 / 列表每一项高度)

但是在不等高的情况下,我们不能通过计算算出下标,而是通过查找。这里我们又要注意,不能使用单粗暴for循环在全部中查找,站在算法的角度来说就是会超时。记录元素高度信息列表是有规律的,top和bottom都是递增的,在这种有明细递增的一组数据中寻找数据使用二分是不错的选择

code.png

具体使用,也是不等高虚拟列表的核心代码 code.png

完整代码

仓库地址

结语

感兴趣的可以去试试