? 当浏览器拿到服务端返回的资源后,第一步是通过一些解释器将文本翻译成计算机能理解的数据结构,先是把html和css转换成DOM和CSSOM,然后将两棵树做一个合并,形成Render Tree,这个时候会把真正要显示的东西留下,不显示的东西去掉,比如某个节点的display为none,在渲染树中就会去掉它。
? 有了这颗树之后它就知道每个节点是什么尺寸,要把它画到什么位置。
? 首次加载,或者页面发生样式上的变化都会有如下5步
JavaScript
可以通过JS实现一些页面上面的视觉的变化,此外CSS动画,过渡,Web Animation API也可以触发视觉的变化,这里的JavaScript只是代表一个总称,代表触发视觉变化
Style
这里浏览器要重新对样式进行计算,根据选择器进行一个重新的匹配,计算哪些元素css受到了影响,新的规则是什么样的,应该绘制成什么样的,有了这些以后每个元素最终应该是什么样就知道了
Layout
然后就到了布局,实际上就是把你的元素按照样式绘制到页面上,这里实际上是一个几何问题,因为你要知道这个元素的大小位置
Paint
绘制,就是真正把东西画到页面上,画文字图片颜色等等,它会和复合,合成联系起来
Composite
复合,合成,为了效率不会把所有东西都画到一个层里,不同的东西画到不同的层,最终再合成到一起显示出来
? 理论上这五个步骤都是要进行的,但是其实有些样式不会影响我们的布局和绘制,所以浏览器进行了优化
? 最重要也是开销最高的两个步骤,我们希望再某些情况下不去触发这两个操作
? 当不是高度,或者offset这样的一些位置信息的话不会触发布局,直接进行重绘,此外有些动画是可以利用GPU进行加速的, 这种动画是可以直接走复合的过程,而无需布局和重绘
? 一般情况下第一次叫做布局,当后面页面变化时导致的布局叫做回流(核心就是位置和大小)
? 有时候回流不可避免,还要避免一个陷阱(layout thrashing布局抖动),当出现回流的时候,
? 为了做动画当你给宽度赋值的时候,如果先获取offsetTop之类的时候可能就会遇到这个,会触发非常频繁的Layout布局操作(Forced Reflow强制回流),浏览器为了提高布局的性能会尽量的把修改布局相关的属性操作推迟,但是这种情况就无法推迟,就是当你要去获得布局相关的属性如offsetTop,就不得不立即去做一个最新的计算以保证你能拿到一个最新的结果,就会导致连续不断的强制回流操作发生,就是布局抖动导致卡顿
所以尽量避免回流
比如修改元素的位置尽量不要修改left,bottom之类的,其实可以用transform: translate
做一个位移,这个动画的特点就是不会发生回流和重绘,只会触发复合的过程
读写分离
像vue,react这种virtual dom,会把触发回流的操作会进行批量处理,统一计算,最后应用到真实DOM,就是说先把读的操作都执行完,再批量的进行写的操作
? 核心就是两个方法
fastdom.measure(() => {// 测量
console.log(‘measure‘)
})
fastdom.mutate(() => {
console.log(‘mutate‘)
})
fastdom.measure(() => {
console.log(‘measure‘)
})
fastdom.mutate(() => {
console.log(‘mutate‘)
})
// 就是实现批量的读和写,达到消除页面抖动的效果
‘measure‘
‘measure‘
‘mutate‘
‘mutate‘
? compositor thread & layers,复合和绘制密切相关,为了提高浏览器效率才有了复合,就是把我们的页面拆解成不同的图层,当发生页面的视觉变化时,有些可能只影响某个图层的变化,而其他图层不需要受到影响,绘制过程就会更高效的完成。
? 浏览器决定是否要拆成多个图层,如果某个元素对其他元素影响较多就会被拆成单独的图层,就可以实现如果它发生变化就只对它这个图层做相关的重绘,不影响其他部分。以下四种情况都只会触发复合,而不是布局和重绘
transform: translate
transform: scale
(可以代替修改宽高等)transform: rotate
opacity: 0
? 如何把动画提取到单独的图层呢,可以在css里加上willChange: ‘transform‘
,注意不能创建过多的图层
原文:https://www.cnblogs.com/hyhwy/p/14855541.html