有些需求需要展示长列表,无限下拉都会一直显示出更多的数据。但是当一个页面展示的DOM节点过多的时候,会造成小程序页面的卡顿严重的会直接白屏。
原因有以下几点:
列表数据很大,不断获取下一屏的数据,setData的数据越来越多的时候耗时高
渲染DOM 结构多,每次 setData 都需要创建新的虚拟- 树、和旧树 diff 操作耗时都比较高
DOM 结构多,占用的内存高,造成页面被系统回收的概率变大,会白屏
针对这个场景,小程序官方已经有一个解决方案recycle-view:但是使用之后,我发现了很多问题,比如下一页的页面渲染不完整,或者拉取下一页的数据会闪屏。
这些问题都已经反馈给相关开发,但是还没有得到回复,所以我也不确定是不是我没有用对,万一等了半个月最后得到的结论是,官方组件不能满足我们的场景,那就GG了。所以我只能暂时先追求另外一种解决方案了。
通过查看官方文档跟组件代码,可以看到他们的实现思路是这样的:
由此我猜想,为什么会出现渲染不完的情况,应该是由于它需要靠着用户提供的item的高度来算哪些item需要渲染,然后来计算应该渲染出来的屏幕高度。那如果这个计算渲染屏幕高度偏少,就会有渲染不完的情况,计算的高度偏多,又会有渲染出空白的情况。当然我没有去调试它的代码,毕竟看别人的代码是痛苦的,只是瞎猜一通而已。
既然我猜他是因为高度的问题,才出现那么多问题,同时依赖用户提供高度我觉得总是不靠谱,万一他给错了,就会使得渲染有问题。可不可以不要知道item的高度也可以知道哪些元素被渲染出来呢?
答案是可以的。
我们可以以一屏为一个单位,而不是以一个item为一个单位,这样我无需开发者给我提供他的高度。我自己去记录每一屏的高度,然后onscroll的时候,根据scollTop来计算当前应该渲染哪一屏,我把它首尾两屏的元素也一起加起来算是我总的需要渲染元素。
有人可能会说:如果我是一屏拉取所有的数据而不是分屏,那你这个方法就不可行了。确实是这样的,但是我觉得应该没有什么场景需要一次性拉取所有的数据。原因如下:
1、一屏你拉取所有节点,用户根本看不完,所以意义不大
2、数据太大,造成网络传输慢
3、setState也慢造成首屏慢
我感觉没啥好处,坏处倒是挺多的。所以不太建议一屏直接返回所有数据。