css 重排与重绘

2019/04/10 10:10
阅读数 15

css 重绘与重排

<div style="text-indent: 2em">我们要知道当浏览器下载完页面的所有资源后,就会开始解析源代码。</div> <div style="text-indent: 2em">HTML 会被解析成 DOM Tree,Css 则会被渲染成 CSSOM Tree,最后它们会附加到一起,形成渲染树(Render Tree)。当渲染树构建完成时,就会开始绘制页面元素。</div> <div style="text-indent: 2em">这时如果 DOM 发生更改或者元素的 css 几何属性发生变化,比如 width,height,position 定位等。那么就会引发一次浏览器的重排/重绘过程,也就是浏览器会重新计算元素的几何属性,并重新构造渲染树,这个过程叫做重排,完成重排后,要将重新构建的渲染树渲染到屏幕上,这个过程就是“重绘”。</div> <div style="text-indent: 2em">而如果是 css 的非几何属性更改,则只会引起重绘。所以说重排一定会引起重绘,而重绘不一定会引起重排。</div>

重排

<div style="text-indent: 2em">既然重排的原理是根据因为几何属性发生了改变,那么我们就能够总结一下引起重排的操作:</div>

<div style="text-indent: 4em">1、页面首次渲染</div> <div style="text-indent: 4em">2、添加或删除 Dom 的显示与隐藏</div> <div style="text-indent: 4em">3、元素相对于文档的定位改变</div> <div style="text-indent: 4em">4、元素的大小尺寸改变</div> <div style="text-indent: 4em">5、添加行内 style 样式</div> <div style="text-indent: 4em">6、浏览器窗口大小发生改变时</div>

重绘

<div style="text-indent: 2em">重绘相对来说就简单点了,比如颜色改变,背景图片改变,阴影改变等,只要不影响元素本身相对于浏览器文档的位置只会触发重绘。</div>

性能优化

<div style="text-indent: 2em">操作 DOM 的成本是非常高的,而且如果不小心改掉元素的几何属性,就会触发重排和重绘,这时就会影响用户体验。我们来看一个简单的例子:</div>

var box = document.getElementById('box'); // 获取页面一个子元素
    box.margin = "15px"; // 重排+重绘
    box.border = "1px solid red"; // 又是一次重排+重绘
    box.backgroundColor = "red"; // 没有尺寸变化,只重绘
    box.fontSize = "16px"; // 重排+重绘
    // 新的DOM节点 - 重排+重绘
    document.body.appendChild(document.createTextNode('!!!!'));

<div style="text-indent: 2em">只改当前页面中的子节点,可能影响不是很明显,如果修改的节点多了或者修改了页面的顶级节点属性,那么就会推动整个页面的变化,代码是十分昂贵的。</div>

<div style="text-indent: 2em">因此,从性能优化角度,我们可以从以下几个方面着手:</div>

<div style="text-indent: 2em"><strong>1) 浏览器本身的优化策略</strong></div>

<div style="text-indent: 4em">浏览器会维护一个队列,将所有引起重排和重绘的操作都放在这个队列里,当操作达到一定的数量或者时间间隔时,浏览器会批量执行来优化重排过程。这样可以让多次的重排重绘,变成一次。但是有的特殊 style 属性会使这种优化失效,例如offsetTop,scrollTop,clientTop等属性,这些属性都是要实时返回给用户的几何属性或者布局属性,因此浏览器需要立即执行,触发重排返回正确的值。</div>

<div style="text-indent: 2em"><strong>2) 最小化重排和重绘</strong></div>

<div style="text-indent: 4em">避免设置大量的 style 行内样式。修改单个 DOM 节点的多条语句合并成一个语句来执行。</div> <div style="text-indent: 4em">DOM 元素的动画属性最好设置为 absolute 或者 fixed 定位。</div>

<div style="text-indent: 2em"><strong>3) css 动画和性能处理</strong></div> <div style="text-indent: 4em">减少 js 操作元素的样式,使用修改 class 类名方式修改样式。</div> <div style="text-indent: 4em">开启动画的 GPU 加速,渲染计算交给 GPU 处理。</div> <div style="text-indent: 4em">避免频繁计算样式,可以缓存变量,并且在变量中工作。</div> <div style="text-indent: 4em">可以使用 querySelectorAll() 获取的静态集合替代 getElementByXX() 获取的动态集合。</div>

小结

<div style="text-indent: 2em">虽然篇幅不长,但是感谢你看完了这篇文章,最后我来总结一下几个点:</div> <div style="text-indent: 2em"> <ul> <li>重排一定会引起重绘,而重绘不一定会引起重排。</li> <li>会引起重排和重绘的条件</li> <li>怎样进行性能优化(减少 DOM 操作、高性能 API 的使用、开启硬件加速、减少 DOM 操作等)</li> <li>浏览器本身的优化策略</li> </ul> </div>

原文出处:https://www.cnblogs.com/earthZhang/p/12613939.html

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部