前言
场景是小程序长列表优化,框架基于mpvue,固定高度。(动态高度暂时先不考虑)
关于recycle-view
微信官方的提供的recycle-view,是原生的小程序组件。但如果你是基于mpvue框架的话,对第三方原生组件可能不太友好——花了很多时间,最终也没有个所以然,所以就改方案自己来好了。
如果你想要尝试的话,下面的一些坑可以看下:
1.这里是mpvue官方对于第三方原生组件的建议,mpvue官方是建议原生和mpvue做分离(ps:感觉很麻烦)。如果只是想引入第三方原生组件,做法可以参考这里。
2.在完成引入第三方组件后,如果直接按官方文档的写法,会出现 page.selectComponent is not a function
的报错,因为mpvue的this和原生的this指向不同,所以应该使用this.$mp.page
3.后面出现了调用append后页面没内容的情况,也没的办法了,在看了recycle-context源码和社区后,还是算了吧
(ps:源码内部其实是利用page自身的forceUpdate,来强制刷新;社区也有类似的问题,但没人解答;出于时间考虑,就没用这个了;说不定思路在recycle-view其他源码上)
如果有人弄出来了,请留言指导,感谢大佬。
回到虚拟列表
大致原理:
控制滚动元素在可滚动区域中的位置,使其显示在可视区域
- 滚动元素区域:虚拟列表一般滚动元素只是全部数据中的一小部分,可人为设置,可以为3倍可视区域,也可以跟可视区域一样,
- 可滚动区域:全部数据的渲染后的区域
- 可视区域:浏览器可视窗口大小、手机可视窗口大小
假设手机为375 * 667, 有1000条条数据需要渲染,每条高60, 滚动元素区域
那么 滚动元素区域 有60 * Math.ceil(667/60),可滚动区域 为 1000 * 60,可视区域 为667
大体步骤为:
1.通过触发scroll滚动事件,计算出startIndex、endIndex
2.根据starIndex、endIndex计算出滚动元素区域
3.根据starIndex、endIndex计算startOffset、endOffset
4.渲染
实际在DOM实现上有两种思路:
- 一是通过padding-top 和padding-bottom来设置startOffset、endOffset从而撑起可滚动区域的高度,从而可以滚动
//可视区域
//滚动区域
- 二是一开始设置好可滚动区域高度,通过移动元素区域来实现,
//可视区域 position:relative
// 可滚动区域
//元素区域 position:absolute
推荐使用第二用,translate3d可开启硬件加速,提升渲染性能
关于动态高度
还没实践过,后续再补充
参考:
1.浅说虚拟列表的实现原理
2.再谈前端虚拟列表的实现
3.前端长列表原理及优化
4.长列表渲染实践
5.一个简单实现的vue虚拟列表