【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模拟滚动的痛点则是有具体场景的限制和整体的重构成本,两种方案各有千秋,具体使用还需要看具体的使用场景,所以,聪明的你,告诉我?我们需要无线滚动列表么?
【js】我们需要无限滚动列表吗?的更多相关文章
- Android 高级UI设计笔记09:Android如何实现无限滚动列表
ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们提供了一个良好,整洁的用户体验 ...
- Android 高级UI设计笔记09:Android实现无限滚动列表
1. 无限滚动列表应用场景: ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们 ...
- Vue组件封装之无限滚动列表
无限滚动列表:分为单步滚动和循环滚动两种方式 <template> <div class="box" :style="{width:widthX,hei ...
- 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多
通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...
- 【转】超酷的 mip-infinitescroll 无限滚动(无限下拉)
写在前面 无限滚动技术(又叫做无限下拉技术)被广泛应用于新闻类,图片预览类网站.对用户来讲,使用无限滚动的页面有源源不断的信息可以预览,增加用户在页面的停留时长.技术上原理也很简单,在页面加载时加载一 ...
- jquery实现无限滚动瀑布流实现原理
现在类似于pinterest这类的表现效果很火,其实我比较中意的是他的布局效果,而不是那种瀑布流. 虽然我不是特别喜欢这种瀑布流的表现样式,但是还是写了几篇关于无限滚动瀑布流效果的文章,Infinit ...
- Jquery制作--循环滚动列表
自己模仿JQ插件的写法写了一个循环滚动列表插件,支持自定义上.下.左.右四个方向,支持平滑滚动或者间断滚动两种方式,都是通过参数设置.JQ里面有些重复的地方,暂时没想到更好的方法去精简.不过效果还是可 ...
- Infinite Scroll - jQuery & WP 无限滚动插件
无限滚动(Infinite Scroll)也称为自动分页.滚动分页和无限分页.常用在图片.文章或其它列表形式的网页中,用来在滚动网页的时候自动加载下一页的内容.Infinite Scroll 这款 ...
- LoopBar – Tap酒吧与无限滚动
相约 LoopBar – 标签栏与无限滚动为Android由Cleveroad 在Cleveroad我们最近认识到通过使用任何一个应用程序类别的导航,导航面板是很无聊和琐碎.这就是为什么我们的设计师的 ...
随机推荐
- 怎样使用alsa API
翻译文章的链接: http://equalarea.com/paul/alsa-audio.html 关于怎么使用ALSA API教程 这份文档帮助对ALSA API使用入门.不是一个完整的ALSA ...
- FindBugs规则整理
http://blog.csdn.net/jdsjlzx/article/details/21472253/ 配置FindBugs和常见FindBugs错误 http://blog.csdn.net/ ...
- 在Angular.js中的H5页面调用Web api时跨域问题处理
/// <summary> /// 被请求时 /// 在Angular.js中的H5页面调用Web api时跨域问题处理 /// </summary> /// <para ...
- mpvue微信小程序分包
## 微信小程序分包(mpvue) 使用mpvue分包示例:1.下载vue脚手架(先有node环境,v8.12.0) npm install -g vue-cli 2.先用vue初始化一个mpvue小 ...
- 「LOJ#10015」「一本通 1.2 练习 2」扩散(并查集
题目描述 一个点每过一个单位时间就会向 444 个方向扩散一个距离,如图所示:两个点 a .b 连通,记作 e(a,b),当且仅当 a .b的扩散区域有公共部分.连通块的定义是块内的任意两个点 u.v ...
- Subset Sums
链接 分析:dp[i][j]表示前i个数能够组成j的对数,可得dp[i][j]=dp[i-1][j]+dp[i-1][j-i],所以最后dp[n][sum/2]既是所求 /* PROB:subset ...
- tyvj1940创世纪——贪心(基环树)
题目:http://www.joyoi.cn/problem/tyvj-1940 基环树的样子,看了书上的讲解,准备写树上DP,然后挂了: #include<iostream> #incl ...
- js 拦截 窗体关闭事件
<script type="text/javascript"> <!-- window.onbeforeunload = onbeforeun ...
- Mike and distribution
题意: 给定 $n$ 个物品,每个物品有两个属性$a_i$, $b_i$,求一个长度为$[\frac{n}{2}]+1$的子序列 $p$ 使得 $2 * \sum_{i = 1}^{|p|}{a_{p ...
- 爬虫库之BeautifulSoup学习(二)
BeautifulSoup官方介绍文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html 四大对象种类: Beau ...