Skip to content
文章目录

虚拟列表

作用

优化某个组件 有大量数据时,渲染了巨多的 dom 节点,造成的界面卡顿或卡死

原理

通过 js 计算的方式,只渲染视口内的 dom 节点

实现方案

  • 通过监听滚动,仅实时渲染当前视口中,应该展示的数据
  • 通过 css 的 translateY ,修正,当实际渲染的数据发生变化时,渲染区域与可视区域偏移的问题
  • 加入缓冲数据,缓解白屏问题

实现方案中需要用到的实际技术

  • js 获取容器/视口高度: dom.offsetHeight
  • 通过 arr.slice(start,end) 截取,需要随着滚条的滚动,动态展示的数据
  • 通过 css 的 translate 修正渲染区域与可视区域偏移的问题
  • 通过 js 获取 scrollTop(滚动条的滚动高度) dom.scrollTop

为什么要能自己实现一个虚拟列表组件?

  • 别人提供的不一定符合你当前的项目需求,或者在你当前环境下跑起来有问题
  • 网上开源的过于复杂(可能开源的考虑了很多复杂情况),一旦有问题,普通开发者是无力修复问题,而开源者可能又无法及时修复你遇到的问题

相关概念

  • 渲染区:真实数据 dom 节点构成的区域
  • 视口区:可见区域
  • 滚动容器:会出现滚动条的 dom 节点

定高虚拟列表

定义 dom 结构,完成初始化

监听滚动使数据随着滚动而发生变化

当数据发生变化时,修正内容容器的偏移量

当渲染区域的数据发生变化时,修正内容容器的偏移量,使渲染区域处于正确的视口位置

加入缓冲数据,缓解白屏现象

滚动到底部加载更多

不定高虚拟列表

定义 dom 结构,完成初始化

update 之后重新计算当前每个元素的高度和位置信息

监听滚动,并修改 start(让数据随着滚动而改变)

监听滚动,并修正内容容器的偏移量

监听滚动,并修正大数据量卡顿问题

卡顿问题重现

卡顿问题解决

快速拖动到最底部再慢慢往上滚动时的位置偏移问题解决

滚动容器宽度改变时不能保持原本的滚动位置问题解决

加入缓冲数据,缓解白屏现象

使用二分查找优化获取 start 值的方式

滚动到底部加载更多

扩展

基于虚拟列表的 select 组件

参考资料

「前端进阶」高性能渲染十万条数据(虚拟列表)

Vue 移动端企业级实战 - 长列表虚拟滚动高阶插件封装

infinite-scroll-sample