image.png
image.png

有几个前提条件

容器是黑线框container—绑定scroll事件,故黄色那层wrapper会滚动,里面的蓝色item都相对于黄层绝对定位,且item都是定高—>黄层总高度
黄层一动,蓝色item自然而然就跟着动了。
所以重点在于每次显示的是哪些items,放在一个渲染池中。一滚动后,就得更新渲染池里的数据,同时更新位置信息。
不满足这些条件,尤其是不定高时,虽然有解决办法,但会损耗大量性能,毕竟要重新计算高度导致reflow。

实现—Vue版

  1. // 给黑色层div,即container上,绑定@scroll事件处理函数为setPool
  2. methods: {
  3. setPool(){
  4. const scrollTop = this.$refs.container.scrollTop;//container就是黄层div的ref
  5. const height = this.$refs.container.clientHeight;
  6. let startIndex = Math.floor(scrollTop / this.itemSize);
  7. let endIndex = Math.ceil( (scrollTop + height) / this.itemSize);
  8. startIndex -= prev;// 这是让它前后分别多显示几个item
  9. if(startIndex < 0){
  10. startIndex = 0;
  11. }
  12. endIndex += next;
  13. let startPos = startIndex * this.itemSize
  14. this.pool = this.item.slice(startIndex, endIndex).map((it, idx) => ({
  15. item: it,
  16. position: startPos + i * this.itemSize,//每次滚动后item的起始位置--top值
  17. }));
  18. }
  19. }

有现成的插件

  1. npm install vue-virtual-scroller

RecycleScroller:跟我们实现的是同一类
DynamicScroller: 是item高度不确定的情况下,但是同样,不可避免的会损耗更多的性能