简介: ### 背景 团队目前的 Web 端产品中须要显示两个列表视图:卡片列表和条目列表,并且在点击切换按钮的时候,对两个列表进行切换显示。 ![条目列表](https://ata2-img.oss-cn-zh
背景
团队目前的 Web 端产品中须要显示两个列表视图:卡片列表和条目列表,并且在点击切换按钮的时候,对两个列表进行切换显示。
在开发实现进行简略性能测试时,发现列表数量达到数百条后,切换视图就会造成显著的页面卡顿,用户体验很差。于是着手进行性能优化。
第一次优化:解决已知问题
因为我的项目是应用 Vue.js(以下简称 “Vue”)来实现,所以首先查看 Vue 是否存在性能瓶颈,如果存在则思考替换 Vue 进行优化。
通过查看官网给出的 benchmark 后果,咱们能够得悉 Vue 的列表渲染性能在高亮和替换列表元素的时候新能较差,在创立列表和新增列表元素的时候性能都是不错的,执行工夫在毫秒级别。
既然 Vue 并没有给咱们制订太低的性能天花板,那么咱们能够在应用 Vue 的根底上持续进行性能优化。
再来看看代码,点击切换的时候到底产生了什么。
点击事件触发后会引起组件属性 cViewType
变动,而后两个视图的列表会依据 cViewType
的值进行渲染。局部代码如下:
<section class="file-card-list" v-if="cViewType =='card'">
......
</section>
<section class="file-line-list" v-if="cViewType =='line'">
......
</section>
这里通过 v-if
指令来实现列表切换,每次切换时都会销毁之前的视图列表,而后创立一个新的视图列表。在列表元素十分多时,会造成大量的 DOM 元素创立和销毁,性能开销是很低廉的。
所以进行优化的最简略形式就是缓存曾经渲染的列表。对应到代码也很简略,就是将 v-if
改为 v-show
,这样就能够通过 CSS 来管制两个列表的显示 / 暗藏,从而防止 DOM 元素的反复创立。
改变之后成果的确也非常明显,事件仿佛到此结束,但如果列表数量减少到一两个数量级,比方达到一万,是否仍旧晦涩呢?
第二次优化:排查可能的问题
当我将列表元素数量减少到一万之后,卡顿问题果然再次出现了。
而浏览器页面卡顿无外乎两个起因,要么脚本引擎在执行 js 代码,要么渲染引擎在渲染页面。
因为后面曾经对脚本引擎执行 js 代码的问题进行过优化,这一次咱们将优化方向转向渲染引擎。
渲染引擎程序须要借助 CPU 来执行渲染操作,而 CPU 自身并不擅长于解决批量图形渲染,所以能够把这部分的渲染工作交给 GPU。
通过设置 CSS 款式就能够调用 GPU,上面是一种实现形式。
- 首先将两个视图列表都设置为相对定位,脱离文档流。
- 而后在点击事件中动静批改视图列表的 z-index 属性,管制两个列表的层叠关系,通过让一个列表笼罩另一个列表来实现显示 / 暗藏成果。
这里须要留神的是,尽管只有让卡片列表脱离文档流就能够达到成果,但因为条目列表高度超过卡片列表,导致在显示卡片列表时底部依然呈现条目列表元素,所以将两个元素都设置为相对定位,并且让其领有各自独立的滚动条。
优化之后,万张图片能够实现毫秒级切换,十分顺滑。
第三次优化:思考计划的副作用
世上没有银弹,即便借用 GPU 来减速渲染仍会产生一些副作用。
因为 GPU 对渲染图形数量不敏感而对渲染次数敏感,而浏览器对申请的并发数(一次并发 8~6 个申请)又有限度,这在肯定水平上会减少 GPU 的渲染次数,从而影响用户体验。
对于这个问题能够通过 HTTP/2 协定晋升并发能力或者采纳分批预加载的形式(等一批图片资源都预加载完再更新到卡片列表)。
因为这些计划还没有来得及实际,这里就不具体开展了~
总结
针对不同性能问题的场景,优化的伎俩很多,总体上咱们只须要抓住两条线索就能找到适合的解决方案,别离是:做减法和做除法。
- 做减法就是间接缩小操作步骤或资源大小,比方第一次优化中通过
v-show
来进行缓存,就是缩小创立列表的操作。 - 做除法就是对耗时的操作进行拆分。比方第二次优化中,耗时的渲染操作转交给 GPU 来执行。
原文链接
本文为阿里云原创内容,未经容许不得转载。