今天的主题是前端人一生至少要遇到一次的问题,长列表的性能优化。这个问题也是出现在我手头的这个项目里面,突然觉得epr这个项目是个宝藏,它push我前进,哈哈哈哈哈。
进入正题,这次的需求是展示用户两年内的所有数据,并且一份数据需要在一个页面展示三种不同的样式,如下:
其中的chart样式是默认展示2年内所有数据,这里就会有个大坑了,后面会说。在后端给回数据后,我拿到了超1000+的数据,在渲染的时候最明显的现象就是接口已经调用完成,但是页面空白了大概3s才正常展示页面,而且在进行数据的filter和List样式切换的时候也是出现明显的卡顿,这肯定是一次性创建超过1000+的dom后果了,先看List样式的优化,主流的方案就两种,虚拟长列表和分页展示,原理都是尽可能减少dom的创建,第一种是只绘制可视区域的数据,第二种是控制每次渲染的数据量,我在进行这两种方案前也做了其他小细节的优化,比如减少每条row上div层级,去掉不必要的dom元素;给元素设置唯一的key,对于数据量大的情景,设置唯一key是有效提高渲染的方式;通过对比props的变化避免不必要的更新,这里如果是类组件就应该写在如下的生命周期内:
我在项目里使用的是函数组件react-hook的写法,因此使用了memo来达到效果,通过传入管理的数据数组来控制,如下:
经过这些小优化后,在数据量大的情况下效果确实是不能立竿见影,但好过没有,现在来看虚拟列表和分页方案,我选择的是分页的做法,通过监听scroll事件,滑动到页面底部自动插入下一页数据,选择的原因是客户不愿意添加虚拟长列表的第三方组件,涉及到安全问题,他们会很谨慎对待第三方组件的引入,而且我在查看了react-virtualized这个组件,上手略显复杂,直接放弃了,分页方案主要的技术点就是监听scroll事件并判断滑动到页面底部,直接上图:
在滑动的元素上添加下框的事件:
然后在事件回调内部加上滑动到底部的判断:
这个触发频发的操作建议加上防抖功能,后面的分页逻辑就大家发挥了,到这里List的优化就完成了,如果对虚拟列表感兴趣可以自己看看:https://www.npmjs.com/package/react-virtualized
接下来回到chart列表的优化,前面说到的坑就是在这,它默认展示2年内所有的数据,那么虚拟列表和分页方案就都不满足了,在这里我用到了一个分片的方案,就是一次渲染100条,分n次渲染完成:
通过对总刷新次数和当前的次数做逻辑来实现渲染n次的要求,方案也解决了卡顿问题,但是有个缺点,就是能直观的看到数据在逐步增加的刷新动画,一窜一窜的,使用window.requestAnimationFrame方法有可能解决,如果客户不接受这个效果,那也是没办法的事。如果项目里面的chart第三方组件用的echart来做应该就不会出现这个性能问题,echart号称渲染千万级热点图无压力,本项目用的库是基于svg来做绘制的,所以扛不住大量数据,也是没办法的事情,不管能不能接受,我们打工人至少try my best了,客户不是那种sb,肯定都会理解并换方案的,我的客户显然很合理,哈哈哈哈哈。
在做 chart方案时,我也第一次使用了Google的Performance面板来调试性能,查找卡顿的点在哪?毕竟用事实说话才能让客户知道我们没忽悠,这里大致讲讲performance面板的使用,还是贴一个别人的详细介绍:https://blog.csdn.net/weixin_44135121/article/details/103998869,插入我的图片:
我这里就不多做介绍面板详细细节了,只告诉大家怎么查找卡顿的具体函数在哪,找到火焰图Main的那一栏并点开,看哪些task上有红色的小三角,这个代表任务耗时过长了,鼠标放上去就会知道这里的耗时时长和大致的耗时原因,选择这一个task,并且滚动鼠标滑轮一直扩大到最大,再往下面查看Summary那一栏,找到Bottom-Up那一栏,就可以看到耗时最长的函数了,查看最右边的函数名称并点击去具体的函数页面,自己进去对应优化就行。这也是我这次实践的简单心得,大家有谁对performance使用6的也可以留言,向你们学习。
做个总结,长列表优化方案:虚拟列表、分页、分片做法以及小细节优化,大家自行选方案,今天就到这了,欢迎各位留言讨论,有不严谨的欢迎指出。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!