jq 下拉加载每次只执行一次_记一次 无限列表 滚动优化
背景
长列表优化
, 是页面性能优化
中的一个比较常见的问题,也是面试中的常客。
刚好最近在的项目中, 遇到了一个长列表的性能问题,试过多种方案, 最后得以解决。
今天就给大家分享一下。
正文
场景描述
用户需要批量修改 Product中 sku 的 映射关系,可以选择的 Product 的 数量不限
。
每一条sku 对应如下结构:
因为可以选择的sku数量是不限的, 又不能分页, 只能做到一个列表里。
于是, 长列表出现了。
刚开始的方案是做一个虚拟列表
。
具体就是通过监听sroll事件,每次滚动后计算一般元素位置(top和height)
然后,通过渲染三屏的方式,把一段数据渲染到页面上。
数据量不多的时候, 没什么问题。
当选择几百上千条sku 的时候, 快速滑动, 就开始出现卡顿。
如图所示:
作为对比,看一下优化后的效果:
问题定位
在chrome调试工具下,边拖动列表边观察dom的变化。
发现,dom的卸载/挂载/更新的情况都出奇地慢,鼠标已经停下来,能明显感觉到过一会dom才装载完成,所以很可能是dom的渲染性能问题。
定位到渲染性能有问题的dom身上,即每一个 Item(renderFakeTable)。
使用普通文本代替Item,在同样多数量的列表情况下,简单的dom明显会顺畅很多,但是,仍然会出现空白问题。
继续观察renderFakeTable中的每一个元素(可以借用devTools Profiler)。
最简单粗暴的方式就是去除某一类的组件,然后通过不断自测的方式,找出最有可能影响渲染效率的元素:
SearchSelect(基于antd的Select封装的一个业务组件)。
所以,影响渲染性能的元素很可能就是它。
渲染性能
除了组件的问题,还有可能是渲染
的问题。
首先,原来无限滚动的逻辑就是基于scroll事件,通过不断滚动触发的回调,重新计算渲染到页面上的区间。
其次,为了动态调整可视区域的元素,使用了MutationObserver。
导致空白问题则会有这几种可能:
- 没加防抖,频繁渲染带来性能消耗
- scroll 和 MutationObserver 相继执行了渲染,导致dom出现了跳动的现象。
- 预留的元素个数,viewPrepareCount太小了,导致拖动太快时,后面或前面都没有多余的可见元素
- 没有开启GPU加速,应该使用transform代替top来定位到正确位置
不幸运的是,以上的可能都一一排除后,发现几乎没有啥提升。
其实,在第二点缩小范围时,应该意识到,空白问题/拖动不流畅均是因为渲染性能低下
导致的
测试验证
1. 虚拟列表 rc-virtual-list
为了验证是Select 组件的问题,基于:
rc-virtual-list
做了一个在线 demo :
在线地址:https://codesandbox.io/s/optimistic-bartik-69ygc?file=/src/animation.tsx
动态演示:
这里渲染了1000 条记录, 每条记录里有5个select;
默认使用的是 antd Select, 几乎拉不动;
切换到原生select之后, 如丝般顺滑。
由此可以确定,卡顿是 Slect 组件引起的。
所以要减少渲染成本:
- 减少自己的父组件渲染成本,React.memo/React.useMemo/React.useCallback.
- 减少Select渲染成本(比较麻烦,而且效果不明显。经过自测,仅仅是使用一个基础的Select,rc无限滚动的情况下同样发生了卡顿)
2. 下拉懒加载
基于 Intersection Observer
实现一个 下拉懒加载。
利用 Intersection Observer 实现:
在列表的底部(也可能是底部偏上的某个位置)插入一个observer-dom元素.
通过Observer来观测其是否在可视区域中,如果在,那么就往下加载更多的内容:
初始状态时,列表会多渲染几条数据(两屏数据),observer-dom元素一直被顶到底部.
用户往下滚动时,observer-dom元素“出现”在用户视野。
每次多加载一屏的数据,循环如此,直到整个列表都渲染到页面上。
在线demo: https://codesandbox.io/s/gundongjiazai-antd491-forked-vtchw?file=/index.js
动态演示:
选择方案
- 要么接受使用rc无限滚动的不够流畅;
- 要么使用 Intersection Observer 实现一个下拉懒加载的无限滚动效果
最终采用下拉懒加载。
总结
通常,无限滚动的方案可以分为两种:
1. 虚拟长列表
优点:可以保证渲染在页面上的dom元素尽可能少
缺点:如果没有特殊处理(比如rc或锁定滚动区域),快速滚动时,基本都会有闪动的情况(也就是本次的空白问题)
2. 下拉懒加载
优点:防止用户快速拖动的出现闪动问题。再通过加一个loading效果,帮助优化体验
缺点:当用户把列表拉到底,整个列表都会被渲染到页面上
在选择虚拟长列表or下拉懒加载之间的取舍时,可以参考:
如果闪动问题可以接受(组件渲染没有太大性能问题),而且对dom数量要求很严格,那么选择虚拟长列表会更好。
如果闪动问题不能接受,而最终的dom数量能够接受,那么选择下拉蓝加载会更好。
无论是选择虚拟长列表or下拉懒加载,在使用监听scroll事件或者Intersetion Observer API之间的取舍时,可以参考:
- scroll的事件回调会在主线程中被成千上万次调用,尽管加了防抖
- scroll的方式,需要不断记录scrollTop和元素高度
而使用Intersetion Observer API,上述几点的计算就可以省略了,优化工作交给了浏览器。如果不考虑IE 等, 它是一个不错的选择。
内容就这么多, 希望对大家有所启发。
如有错误, 欢迎指正, 谢谢。
jq 下拉加载每次只执行一次_记一次 无限列表 滚动优化相关推荐
- 微信小程序下拉刷新列表onPullDownRefresh;微信小程序上划加载列表onReachBottom;uni-app微信小程序下拉加载数据;uni-app微信小程序上划页面加载数据
需求:微信小程序列表加载有两种方式,分别是按住页面下拉加载数据数据(触发onPullDownRefresh)和直接上划滚动页面到底部加载数据(触发onReachBottom函数). 本文主要是使用上划 ...
- 不使用输入框如何实现下拉_使用INFINITE AJAX SCROLL实现下拉加载效果
现在很多网页都有个体验不错的效果:浏览到页面底部的时候,自动加载下一页内容,也就是下拉加载效果,这种效果可以让用户不用点击"下一页"按钮,也可以实现翻页,无论在PC还是手机上,体验 ...
- 织梦ajax加载文章列表,织梦dedecms首页列表页ajax点击下拉加载更多文章瀑布流效果...
织梦dedecms实现点击下拉加载更多主要用到ajax技术.具体步骤如下: 一.首先找到并打开/plus/list.PHP文件,在里面找到如下代码: require_once(dirname(__FI ...
- html下拉加载原理,GitHub - gavinjzx/wxPull: 原生JS实现微信公众号或网页使用下拉加载和上拉刷新...
原生JS实现微信公众号或网页使用下拉加载和上拉刷新 微信浏览器打开网页显示网址安全信息解决办法,网上很多办法,也找了很久,但是最新的很多用不了. 先看看效果,是不是亲想要的,可以跳过,以免浪费宝贵时间 ...
- html下拉加载实现原理,GitHub - sybiele/wxPull: 原生JS实现微信公众号或网页使用下拉加载和上拉刷新...
原生JS实现微信公众号或网页使用下拉加载和上拉刷新 微信浏览器打开网页显示网址安全信息解决办法,网上很多办法,也找了很久,但是最新的很多用不了. 先看看效果,是不是亲想要的,可以跳过,以免浪费宝贵时间 ...
- react 瀑布流和下拉加载以及图片加载
import React from 'react' import Masonry from 'masonry-layout' // 瀑布流 import InfiniteScroll from 're ...
- html5页面下拉加载更多_使您的产品页面销售更多的5条提示
html5页面下拉加载更多 Getting visitors to your website requires a great deal of work and, for many businesse ...
- ASP.NET仿新浪微博下拉加载更多数据瀑布流效果
闲来无事,琢磨着写点东西.貌似页面下拉加载数据,瀑布流的效果很火,各个网站都能见到各式各样的展示效果,原理大同小异.于是乎,决定自己写一写这个效果,希望能给比我还菜的菜鸟们一点参考价值. ...
- IM 聊天页面下拉加载更多--类似微信顺滑展示
背景 领导在会议上说我们的 IM 聊天页面的用户体验不太好,尤其是下拉加载更多会跳动,让我优化一下.之前还确实没有注意到这一点,现场拿出手机和微信做对比,不比不知道,一比还真是发现了问题.微信 ...
最新文章
- 一文运维zookeeper
- weblogic线程阻塞性能调优(图解)
- 基于 Alluxio 的 HDFS 多集群统一入口的实现
- 注意力机制的本质中文版代码
- Xml转换成view的原理
- git、github、gitlab、gitee都是什么?
- NormalMap 贴图 [转]
- .NET Core运行时和基础类库性能提升
- 10以内的分解与组成怎么教_狗狗酷炫的飞盘游戏怎么玩?分解步骤教你快速学会...
- 被讨厌的勇气--总结
- 详解HTTP协议~~~
- 巴萨队徽_巴塞罗那选择Linux,Apple的Lisa OS开源,更多新闻
- matlab求解线性规划问题的实例代码,matlab 求解线性规划问题
- Linux创建shell脚本文件
- tp5 根据身份证号码判断性别 男女
- 武汉大学计算机学院2010情景剧,武汉大学2010届毕业生生源httpwww.xsjy.whu.edu.cn.doc...
- ArcGIS Pro数据加载学习总结
- 如何理解答案-Leo读提问的智慧(4)
- 简单分析软件项目成本管理
- 酷派大神f1,酷派大神f2 无法打log的解决方法。
热门文章
- linux mysql 确认命令_LINUX启动/重启/停上MYSQL的命令(详解)
- MySQL 查询数据表
- MySql数据类型介绍
- java sql server 2016_SQL server 2016 安装步骤
- 二元一次函数最值问题_初二上学期,一次函数方案设计最值问题,两类题目解题思路不一样...
- matlab中结束脚本运行_MATLAB脱单指南
- python请编写程序、生成随机密码_利用Python如何生成随机密码
- 华为手机显示解析服务器返回错误,ajax服务器返回错误
- opencv7-绘制形状和文字
- python库安装错误 in _error_catcher解决之镜像安装