在前端开发中经常会遇到需要滚动、滑动事件的处理,通常会是 移动端的上下拉刷新 与 PC端的无限滚动 其中一种。
在移动端具有很多成熟的处理滑动事件的解决方案,例如 vue-scroller 、better-scroll ... 而 PC 端的处理方案相比较少,最近项目需要造瀑布流实现无限滚动加载图文,小A在此过程中 get 到许多实用的小技巧,在此和大家做分享。
(需求类似上图,来源于 bilibili )
1. 瀑布流的图片优化
如果是选择自己造瀑布流而不是使用第三方库,开发思路肯定会各不相同,这里不作实现算法的研究,主要方向是优化。
瀑布流万变不离其宗:都是加载图文进行排列,那么在图片的处理上,需要进行裁剪、压缩。在进行分页请求数据时,如果单次请求的图片数量比较大,比如 30 张,则使用背景图会略优于前景图,只是略微。
为什么呢?主要是因为两者加载顺序不同,Img 属于 html 标签,background 是 css 样式。按照浏览器的解析机制,html优先解析。
瀑布流的滚动加载是一种高并发资源请求,往往伴随着 20 - 50 个图片地址的请求,Img标签中的 src 请求地址会优先于背景图的加载时间,造成可能产生的请求失败或缓慢时影响页面其他数据的呈现,甚至在后端未做处理的情况下会频繁报出 304 重定向的错误(等待服务器响应是件很要命的事情,在网速发达的今天,等待一个响应可能比下载都慢)。
如果实现算法中使用的是 ‘position’ 定位技术,那么可以采用元素相对本身的 3d 偏移来代替具体的定位值
translate3d 会开启 GPU 硬件加速会获得略微的性能提升,但在较低版本 Chrome、Safari 浏览器下可能会出现闪烁或抖动的现象,可以添加以下样式改善(增加景深、隐藏元素背面)
选择使用 Img 标签的话也会有一些 SEO、语义化方面的好处,当页面呈现里没有太多其他的文字、icon 等资源,配合懒加载会有很好的效果,所以根据项目的实际需求去选择才是最恰当的。
2. 滚动事件的优化
滚动加载数据,我们需要判断用户是否滚动到屏幕底部,判断条件需要取3个值:页面的总高度、滚动条距离 body 顶部的高度、浏览器视口高度。
根据这个思路我们给 window 注册一个滚动事件(使用 Vue 构建):
( scrollY 为获取当前滚动高度,或运算兼容了不同浏览器的取值方法 )
首先,我们取得了我们需要的三个值,进行了计算,判断是否离页面底部的距离小于 100px ,如果小于说明用户已滚动页面至底部,开始进行加载。
这其中有没有什么问题?当然有!
它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。甚至在 Chrome、Safari 下用户的弹性滚动也会触发监听,频繁到什么程度呢?延续上图随手在 Chrome 与 Firefox 下随手滚动得到的触发事件次数:
以及执行我们注册事件所用的时间:
为了保持用户的体验,如何降低滚动事件频率与缩短事件时间就是优化的重点。回头分析我们上面的代码,采用以下手段:
A. 可将视口高度进行缓存,并在 window 注册 resize 事件
B. 页面的总高度是可以在瀑布流的运算事件中去计算出来的,因为页面的高度改变是因为瀑布流的不断加载。(具体算法各不相同,这里不多加说明)
C. 采用 requestAnimationFrame API ,它是用来在页面重绘之前,通知浏览器调用一个指定的函数。这个方法接受一个函数为参,该函数会在重绘前调用。这么做是为了让页面滚动时能够有一个统一的刷新机制(约为16.7ms )。作用很像定时器,配合布尔变量作为的标识符使用可以带来比较明显的滚动改善
D. 强行过滤掉一部分的滚动事件触发,此值不能过大,建议 1 - 5,否则会影响用户的滚动加载体验(滚动条快速滑到底部无响应之类的情况),需在页面性能与用户体验上得到一个平衡点
最后是采取4种方案后的完整片段
3. 结尾
瀑布流也有很多第三方实现,比如特别好用的 vue-waterfall 等,但在优化需求、复盘经验的过程中,对于这类业务需求的底层实现会了解的更清楚详细,可能这种实现思路会启发你其他的功能实现。
小A觉得使用功能库之前,特别涉及算法、性能优化的时候,自己动手造一造再去 github clone 看源码,能打开更多思路 ~
本文来源于:前端滚动事件、瀑布流的优化小技巧-变化吧门户
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧门户观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
- 赞助本站
- 微信扫一扫
-
- 加入Q群
- QQ扫一扫
-
评论