will-change 属性细节太多了,一般人玩不好

416 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情

will-change 被定义为浏览器最后的优化手段,它的作用是告诉浏览器,这个元素将要发生变化,浏览器可以提前做一些准备工作,当元素发生变化时,浏览器就不需要再做一些额外的工作,从而提高性能。

1. 浏览器的更新机制

浏览器的更新机制就是我们常说的重排和重绘,重排是指浏览器重新计算元素的位置和大小,重绘是指浏览器重新绘制元素的外观,比如颜色、背景等。

浏览器的更新机制是这样的:当我们对元素进行一些操作时,比如修改了元素的位置、大小、颜色等,浏览器会将这些操作放到一个队列中,然后在下一次重绘或者重排时,将队列中的操作一次性执行,这样可以减少重绘和重排的次数,从而提高性能。

浏览器为了性能考虑,会将一些操作放到队列中,等到下一次重绘或者重排时再执行,这样可以减少重绘和重排的次数。

这种性能优化的机制称为合成,合成是指浏览器将多个操作合并成一个操作。

2. 图层

上面说了浏览器的更新机制,浏览器在更新的时候做了很多优化,真是为我们操碎了心。

但是,这些优化都是基于图层的,如果元素没有创建图层,那么浏览器就无法对元素进行优化,这样就会导致性能的降低。

那什么是图层呢?图层就是浏览器为了优化性能而创建的一个独立的渲染区域,图层中的元素不会影响到其他图层中的元素,这样就可以减少重绘和重排的次数,从而提高性能。

在浏览器的开发者工具中,我们可以通过图层面板来查看元素是否创建了图层:

image.png

上面的图中可以看到掘金的首页有多少个图层,我们可以通过左侧的图层树来查看每个图层中的元素。

3. will-change

上面说了那么多,都是为will-change做铺垫,接下来我们来看看will-change的具体用法。

will-change是一个 CSS 属性,它的作用是告诉浏览器,这个元素将要发生变化,浏览器可以提前做一些准备工作,当元素发生变化时,浏览器就不需要再做一些额外的工作,从而提高性能。

will-change的值有很多,比如transformopacityfilter等,我们可以根据元素的变化情况来设置will-change的值。

.will-change {
  will-change: transform;
}

上面的代码中,我们给.will-change元素设置了will-change: transform,这样浏览器会预先为.will-change元素创建图层,提前做好准备工作,将可预知的变化提前放在内存中,从而提高性能。

上面我介绍过图层了,will-change可以添加到任何元素上,所以我这里就不截图了,大家可以自己试一下,随便找一个元素添加will-change,然后在开发者工具中查看元素是否创建了图层。

4. will-change的使用场景

通常情况下是不建议使用will-change的,因为它是作为浏览器最后的性能优化手段,如果你的页面中有大量的元素都设置了will-change,那么浏览器就需要为这些元素创建大量的图层,这样就会导致内存的占用过多,从而导致性能的降低。

那么什么时候可以使用呢?我们可以在一些性能要求较高的场景中使用,比如动画、拖拽等。

就是在预知某个元素将来会频繁的发生变化,我们也对这个元素做过了很多优化,发现还是不够,这时候我们可以使用will-change

例如预览图片,图片会有拖动、缩放、旋转等操作,这时候我们可以给图片元素设置will-change: transform,这样浏览器就会为图片元素创建图层,从而提高性能。

5. 总结

今天我们主要介绍了will-change这个 CSS 属性,比较小众,如果在做动画的时候发现各种性能优化都做过之后发现还是差点意思,那么可以尝试一下will-change