为什么element-ui大量使用transition修改元素样式?

4,144 阅读3分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

最近在项目里面做整体换肤的需求,发现切换肤色样式之后,eleme组件的背景色和文字颜色等样式总是比常规元素变化的慢半拍,这让我这个资深强迫症患者怎么能忍? 大家不妨也来康康:

chrome-capture (1).gif

其实原因也很容易被排查出来了,就是因为eleme在组件里面大量使用了transition过渡来处理组件的样式。而且是transition: all .3s;不信咱们来看看:

image.png

那么问题来了:为什么element-ui会大量使用transition修改元素样式呢?这样做会带来什么好处呢?今天我们就来一探究竟。

重排与重绘

我们首先从浏览器的重排与重绘机制说起。

  • 更新了元素的几何属性(重排)

通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的

  • 更新元素的绘制属性(重绘)

如果修改了元素的背景颜色,那么布局阶段将不会被执行,因为并没有引起几何位置的变换,所以就直接进入了绘制阶段,然后执行之后的一系列子阶段,这个过程就叫重绘。相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。

显然重排和重绘都存在一定的性能开销,相类似于hover这样的高频操作,对性能还是十分敏感的,为了更好的用户体验,我们是否有更优的方案来规避主线程的性能开销呢?答案就是transition

CSS 的 transform或transition 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作。这样的效率是最高的,因为是在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率。

没错,eleme中除了在背景色、边框、颜色上使用transition,在一些按钮的定位上、元素的居中显示上(所以你知道了更优的居中显示方案了吗?),都大量使用了transition来实现,以此来实现更流畅的视觉体验,当然在我当前的换肤方案里面显然是带来了副作用,但是瑕不掩瑜了。

GPU加速

css3默认开启硬件加速,所以使用css的transition和transform可以Gpu来实现绘制,能够实现更加流畅的显示优化。

综上:你搞懂了为什么element-ui大量使用transition修改元素样式了吗?

补充

关于transform是否有硬件加速的问题,可以看下这位老哥的博客

3D 和 2D transform 的区别就在于,浏览器在页面渲染前为3D动画创建独立的复合图层,而在运行期间为2D动画创建。 动画开始时,生成新的复合图层并加载为GPU的纹理用于初始化 repaint,然后由GPU的复合器操纵整个动画的执行,最后当动画结束时,再次执行 repaint 操作删除复合图层。

个人观点,欢迎大佬们批评指正。可以在评论区留言交流。