zoukankan      html  css  js  c++  java
  • 【js】我们需要无限滚动列表吗?

      无限滚动列表,顾名思义,是能够无限滚动的列表(愿意是指那些能够不断缓冲加载新数据的列表的)。但是,我们真的需要这样一个列表吗?在PC端,浏览器的性能其实已经能够满足海量dom节点的渲染刷新(笔者经过简单的测试,1w+的节点并没有很明显的卡顿),但是同样的dom数量在移动端却不行,在dom结构合理的情况下,能够保持在2K+的dom数量已是一个很不错的列表了,但是dom数量再进一步增加就会明显影响页面的渲染效率,也正因为此原因,才有了此文关于无限列表的一些思考和探索。

      首先,为什么会卡顿?因为dom数量的绝对值上的不断增多,在后续的交互上(如滚动,局部更新)都会导致页面渲染性能的下降。

      那么,应该如何解决?既然是dom数量过多引起的,最简单也最有效的方法自然是减少dom数量。在jQuery时代,笔者便见过一种思路(其实本质实现至今也没有太大的变化):

      1、只渲染特定几屏的数据,将多余的数据缓存在内存中,并不直接实例化到dom tree上,减少dom的绝对数量;

      2、监听滚动事件,在滚动的时候动态的更新dom,让用户在视觉上看不出区别;

      jQuery的实现由于年代久远,已经找不太到了,不过笔者在react社区找到了一个比较好的实现:react-virtualized,值得一提的是,它还将我们的滚动场景区分为了viewport内的局部滚动,和基于viewport的滚动,前者相当于在页面中开辟了一块独立的滚动区域,属于内部滚动(和iscroll的滚动很类似,顺带一提iscroll也给出了iscroll-infinite的解决方案);而后者则把滚动作为了window滚动的一部分(对于移动端而言,在非模态窗的场景下这种滚动更常见,共用一个滚动条也不容易引起用户的误操作)。因为笔者主要的使用场景是后者,而iscroll的解决方案虽然也能作用于页面维度的滚动,但是它需要完全替换scroll事件(相当于页面没有了scroll事件,只有touchmove事件;且此种页面在内部滚动和全局滚动的实现上有不小的难度),所以笔者在无限滚动列表上并没有使用iscroll的方案。

      不过,业内虽然有现成的解决方案固然是好事,但是每种方案都有自己的特性,并不一定都合适,以react-virtualized来说,它的特性在pc上算是一个很有趣也很不错的解决方案了:

      1、它构造一个“足够大”的容器来再现滚动条的实际数值;

      2、它使用绝对定位来不断跟随滚动事件,改变元素的位置,几乎完美还原了正常列表的视觉,而且无论dom再多也不会卡顿;

      不过,与此同时,它也有一些不足:

      1、因为使用了scroll事件,某种程度上,就注定了在ios上的不足(ios scroll时会阻塞js执行),加上它的缓冲区其实是单向的(虽然这也体现了作者想尽可能节省dom的愿景),导致用户如果上下来回滚动,则很容易看到白屏;

      2、由于绝对定位的“小技巧”,它要求在组件渲染之初就必须知道每一行元素的高度,但是这个看起来不起眼的小操作,却很大的影响了开发的体验(很不凑巧的笔者使用的无限列表的场景,很多情况下列表元素的高度都不能预先知道。。)

      也基于以上原因,虽然react-virtualized是很不错的解决方案了,但是笔者最终没有采用。不过,在广泛借鉴了各大厂的实现之后,笔者发现,手淘列表页的实现,最简单也最有效,那么简单说下实现思路:

      1、它引入了分页的概念,在用户不断刷新增加页面长度的同时,它将若干元素分为一页;

      2、然后在滚动的时候计算当前滚动到了具体的哪一页,将“多余”(不需要显示,也不需要作为缓冲显示)的页的高度取出,直接赋值在容器上,然后将容器内所有元素置空;

      3、当“当前页”发生变化时,动态将需要显示“空页”重新加上元素。

      其实这一解决方案也有反复操作dom的性能问题,而且它并不是dom数量优化上的最优解,但是结合笔者的实际使用场景,而且结合考虑到对业务同学的api友好等各方面的,笔者最终也选择了这一实现,虽然各方面性能不是最好,但是在笔者当前的使用场景中,却最是有效的。

      简单的小结一下,其实有关无限列表的实现有很多种方案,使用原生scroll事件的痛点在于ios的js阻塞问题以及如何巧妙的设计缓冲区,而使用transform模拟滚动的痛点则是有具体场景的限制和整体的重构成本,两种方案各有千秋,具体使用还需要看具体的使用场景,所以,聪明的你,告诉我?我们需要无线滚动列表么?

     

  • 相关阅读:
    chrome浏览器中安装以及使用Elasticsearch head 插件
    windows10 升级并安装配置 jmeter5.3
    linux下部署Elasticsearch6.8.1版本的集群
    【Rollo的Python之路】Python 爬虫系统学习 (八) logging模块的使用
    【Rollo的Python之路】Python 爬虫系统学习 (七) Scrapy初识
    【Rollo的Python之路】Python 爬虫系统学习 (六) Selenium 模拟登录
    【Rollo的Python之路】Python 爬虫系统学习 (五) Selenium
    【Rollo的Python之路】Python 爬虫系统学习 (四) XPath学习
    【Rollo的Python之路】Python 爬虫系统学习 (三)
    【Rollo的Python之路】Python sys argv[] 函数用法笔记
  • 原文地址:https://www.cnblogs.com/mfoonirlee/p/7301596.html
Copyright © 2011-2022 走看看