虚拟列表
又名 虚拟滚动
Why
如何渲染大量数据在页面上?
原理
只渲染可视区域
滚动时,计算并更新开始位置和结束位置
vue-virtual-scroll-list
使用:
resized item mounted 时触发
场景:
- 有限数据
- 无限加载
- 横向
- 保持状态,如选中
- 聊天室,现成解决方案
原理:
滚动时通过改变 padding 的值来模拟滚动,里面的每一个 item 在滚动时被动态替换
item 固定高度,可以提前计算出总高度 padding = item-height *
item 高度不定,padding 初始为 0
源码:
h(type, attrs, children) 函数第三个参数是 children
item 用 ResizeObserver 观测自身,触发 resized 事件
virtual-list-item,virtual-list-slot 多组件用 mixin
结构
Virtual 类,虚拟列表核心计算
updateRange 更新 start/end,触发时机?head/footer resized?
javascript - 面试题:渲染十万条数据解决方案_个人文章 - SegmentFault 思否
面试题:渲染十万条数据解决方案 | Azhubaby Blog
懒加载
触底加载,一直追加,较常用
时间分片
一次性渲染是瓶颈,分批渲染
vue-virtual-scroller
grid 和 list,有不同组件
问题:
- scrollToItem 只支持 index,只能滚动该元素到屏幕顶部
- 不确定高度:参考 simple-list demo,需要用指定组件对 item 包一下,以计算 item 高度
源码
数据:pool
滚动: CSS transform
利用 transform 的 translate3d 属性来实现虚拟滚动。这样做的原因是,使用 translate3d 可以触发 GPU 加速,提高滚动的性能。它通过计算列表项的高度,并在滚动时动态地更新 transform 属性,以实现虚拟滚动的效果。
scrollToPosition 计算距离,操作 el.scrollTop scrollDistance 计算
if (this.itemSize === null) {
scroll = index > 0 ? this.sizes[index - 1].accumulator : 0
} else {
scroll = Math.floor(index / gridItems) * this.itemSize
}
pool 数据丢失
需要源码打点 Missing elements after RecycleScroller is displayed · Issue #794 · Akryum/vue-virtual-scrollerSpace between items in the list is wrong · Issue #749 · Akryum/vue-virtual-scroller
将元素滚动到可见区域
scrollIntoView
- smooth 有时看起来像卡,用默认值 instant 更好
- block 表示垂直,inline 表示水平,两者默认者不同,注意使用。
- nearest 与父元素最近的边对齐
images[currentIndex - 1].scrollIntoView({ behavior: 'smooth', block: 'nearest' });