标签:style 浏览器 render 样式 重排 回流 重绘 页面
参考资料:
https://blog.csdn.net/a419419/article/details/90402561
https://kb.cnblogs.com/page/169820/
https://www.cnblogs.com/chenyanlong/p/10551080.html
回流(reflow)与重绘(repaint),在性能优化的时候,经常会提起,因为涉及到浏览器底层的渲染,所以掌握的童鞋并不多,但是面试经常被提及。而且在解决一些bug上,也能派上用场。
1. 浏览器渲染机制
在讨论页面重绘、回流之前。需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程。可能不同的浏览器略微会有些不同。但基本上都是类似的。
-
1.解析HTML以构建DOM树 浏览器把获取到的HTML代码解析成1个DOM树,HTML中的每个标签都是DOM树中的1个节点。
-
2.解析css样式:浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体 ,在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而FF会去掉_开头的样式。
-
3.构建渲染树:DOM Tree 和样式结构体组合后构建render tree,render tree不同于DOM树,render tree能识别样式,render tree中每个NODE都有自己的style,而且 render tree不包含隐藏的节点 (比如display:none的节点,还有head节点),一旦render tree构建完毕后,浏览器就可以根据render tree来绘制页面了。
-
4.布局渲染树:从根节点递归调用,计算每一个元素的大小、位置等,给每个节点所应该出现在屏幕上的精确坐标。 +
-
5.绘制渲染树:遍历渲染树,每个节点将使用UI后端层来绘制。
2. 重绘与回流
回流(reflow)
:发生在第4阶段,当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。
重绘(repaint)
:发生在第5阶段,当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。
特点:
1)每个页面至少需要一次回流+重绘。
2)回流必将引起重绘
回流什么时候发生?
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时;
重绘的产生:
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如
visibility、outline、背景色等属性的改变。
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));
3. 浏览器优化
从上个实例代码中可以看到几行简单的JS代码就引起了6次左右的回流、重绘。而且我们也知道回流的花销也不小,如果每句JS操作都去回流重绘的话,浏览器可能就会受不了。所以很多浏览器都会优化这些操作,浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。
虽然有了浏览器的优化,但有时候我们写的一些代码可能会强制浏览器提前flush队列,这样浏览器的优化可能就起不到作用了。当你请求向浏览器请求一些 style信息的时候,就会让浏览器flush队列,比如:
1.offsetTop, offsetLeft, offsetWidth, offsetHeight
2.scrollTop/Left/Width/Height
3.clientTop/Left/Width/Height
4.请求了getComputedStyle(), 或者 IE的 currentStyle
// 浏览器会维护一个队列, 浏览器并不会立即进行渲染操作
// 将所有的 css 样式操作, 放到队列中, 等 js 执行完, 一次性进行渲染
// 特例: 对于一些获取性操作, 为了保证获取的数值的准确性, 会提前 flush(清空) 浏览器维护的队列, 将其解析渲染
button.onclick = function() {
div.style.height = "400px";
div.offsetHeight;
div.style.transition = "all 1s";
div.style.width = "400px";
}
4. 如何性能优化?
减少回流与重绘的次数,就需要简单对渲染树的操作。
-
直接使用className修改样式,少用style设置样式
-
让要操作的元素进行”离线处理”,处理完后一起更新(使用display:none技术,减少回流和重绘的次数)
-
将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素为动画的 HTML 元素,例如动画,那么修改他们的 CSS 是会大大减小 reflow 。
4. 尽量不要在 for 循环中, 进行样式获取性操作
5. 使用 translate 代替 left/top 等, translate 只触发了 重绘, 不会触发回流, 节约一次回流的时间
6. 通过 opacity 替换 visibility, 改透明度渲染效率更高
7.不要使用table 布局,因为table 的每一个行甚至每一个单元格的样式更新都会导致整个table 重新布局
8.将多次改变样式属性的操作合并成一次操作。
例如JS:
var changeDiv = document.getElementById(‘changeDiv’);
changeDiv.style.color = ‘#093′;
changeDiv.style.background = ‘#eee’;
changeDiv.style.height = ’200px’;
CSS:
div.changeDiv {
background: #eee;
color: #093;
height: 200px;
}
JS:
document.getElementById(‘changeDiv’).className = ‘changeDiv’;
5. 前端工程师面试题(性能优化)https://www.jianshu.com/p/a2d054c58797
※※※※优雅降级和渐进增强?
优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会针对旧版本的IE进行降级处理了,使之在旧式浏览器上以某种形式降级体验却不至于完全不能用。 如:border-shadow
渐进增强:从被所有浏览器支持的基本功能开始,逐步地添加那些只有新版本浏览器才支持的功能,向页面增加不影响基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。 如:默认使用flash上传,但如果浏览器支持 HTML5 的文件上传功能,则使用HTML5实现更好的体验;
标签:style,浏览器,render,样式,重排,回流,重绘,页面 来源: https://blog.csdn.net/weixin_41282726/article/details/96496903
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。