长列表渲染节点数由于较多,直接渲染肯定会造成页面的卡顿,一种方式是滚动加载(infinite scrool),并非一次性渲染全部列表,而在滚动到页面底部的时候,再去加载剩余的数据,二是通过合理的逻辑来限制仅渲染可视区域部分;
当然方式一需要产品设计允许,毕竟滚动到底步才加载的方式对体验有一定折损,而方式二就需要比较复杂的逻辑了。
对于方式二实现的一些思路:
令列表中的每个元素的高度是
itemHeight
, 列表高度是clientHeight
,列表一共10000条数据,总高度为 itemheight * 10000,可视区域列表项数量为visibleCount = Math.ceil(clientHeight / itemHeight)
.
通过onScroll监听当前滚动位置
scrollTop
,计算得到当前位置列表位置序号var start = Math.floor(scrollTop / itemHeight)
,var end = start + visibleCount
, start 和 end 分别记录可见区域开始和结束位置索引;然后截取数据data.slice(start, end)}
渲染到列表上,这样每次仅渲染 visibleCount 数量节点,大大提高渲染效率
给占位元素加上一个
transform = `translate(0, ${fixedScrollTop}px)
,其中fixedScrollTop = scrollTop - scrollTop % itemHeight
.
此方法在某些scroll事件支持不好的浏览器下可能存在问题,另外还有限制列表项高度是固定的
具体实现可查看demo
此外,还思考在快递滚动下是否可以再进一步优化性能,或许可能影响一点点视觉效果,比如: