虚拟滚动列表

1.一次性传入大量数据的情况下,通过滚动数据位置,只显示10条数据

(1)计算可视区域

  • 设定每个列表项的高度(如 itemHeight = 50px)。
  • 计算可视区域内可显示的最大列表项数量: visibleCount=Math.ceil(视口高度/itemHeight)visibleCount = Math.ceil(视口高度 / itemHeight)visibleCount=Math.ceil(视口高度/itemHeight)
  • 示例
    • 视口高度 500px
    • 每个项 50px
    • 可视项数 500 / 50 = 10(最多渲染 10 个)

(2)动态更新 DOM

  • 只渲染可视区域的项visibleData)。

  • 计算 起始索引 startIndex结束索引 endIndex

    startIndex=Math.floor(滚动距离/itemHeight)startIndex = Math.floor(滚动距离 / itemHeight)startIndex=Math.floor(滚动距离/itemHeight) endIndex=startIndex+visibleCountendIndex = startIndex + visibleCountendIndex=startIndex+visibleCount
  • 示例

    • 滚动 150pxstartIndex = 150 / 50 = 3
    • 可见数量 10endIndex = 3 + 10 = 13
    • 仅渲染 list.slice(3, 13),隐藏其它项

(3)监听滚动事件

  • 滚动事件触发后,重新计算 startIndexendIndex,更新 visibleData
  • 通过 transform: translateY() 让可视元素的位置匹配滚动位置。

优化:可以计算缓存区防止太快滚动没计算出来

2.通过懒加载的方式,一次性只传入20条,当最后一条数据进入可视区触发重新请求之后的20条数据:

obFooterLoading() {
  if (!this.bottomLoadMode) return
  const ob = new IntersectionObserver((entries) => {
    if (entries[0].intersectionRatio >= 1) {
      if (this.isLoadingMore) return
      this.$emit('onLoadMore')
    }
  }, {
    threshold: 1.0,
    root: document.querySelector('.vl-select-popover')
  })
  ob.observe(document.querySelector('.vl_load_more_trigger'))
}
  • 监听最后一个元素 是否出现在视口中:
    • intersectionRatio >= 1 表示完全可见,触发 onLoadMore 事件加载更多数据。

posted on 2025-03-15 17:37  ChoZ  阅读(36)  评论(0)    收藏  举报

导航