回流重绘

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 回流重绘

前端面试中“页面的回流与重绘”是性能优化方面经常考察的一个知识点。今天总结一下,有不对或者不全面的地方欢迎指正~

1

在讨论页面重绘、回流之前,需要对页面的呈现流程有些了解,页面是怎么把HTML结合CSS等显示到浏览器上的,下面的流程图显示了浏览器对页面呈现的处理流程。可能不同的浏览器略微会有些不同,但基本上都是类似的。

回流重绘

1

浏览器把获取到的HTML代码解析成1颗Dom树,HTML中的每个Tag都是Dom树中的1个节点,根节点就是我们常用的Document对象。Dom树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等。

2

浏览器把所有样式解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而FF会去掉_开头的样式。

3

Dom树和样式结构体组合后构建Render树, Render树类似于Dom 树,但区别很大,Render树能识别样式,Render树中每个节点都有自己的style,而且Render树不包含隐藏的节点 (比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不影响其它节点呈现,所以就不会包含到 Render树中。注意 visibility:hidden隐藏的元素还是会包含到 Render树中的,因为visibility:hidden 会影响布局(layout),会占有空间。

4

一旦Render树构建完毕后,浏览器就可以根据Render树来绘制页面了。

2

当Render树中的一部分(或全部)因为元素的规模尺寸、布局、显隐等改变而需要重新构建,这就称为回流。

当Render树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,不影响布局,比如background-color,就称为重绘。

    注意:回流必将引起重绘,而重绘不一定会引起回流。

    以上,其实理解起来很容易,所谓的Render树就是识别了几何属性的Dom树,好像我们画人体的时候,Dom树是先确定都有什么,比如四肢,头部,身体,其他器官等;而Render树则是确定这个人的高矮胖瘦,头发是否盖眼睛等。如果我们在绘画过程中发现脖子长了那就惨了,脖子下面都要重画,如果发现只是手指画的有问题,我们只需要重画手指,这就是回流了。当我们的Render树完事了,也就是人体大概轮廓我们都画好了,就可以上色了,换个发色这种我们叫重绘。

举个栗子🌰:


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

当页面布局和几何属性改变时就需要回流,下述情况会发生浏览器回流:

页面渲染初始化

添加或者删除可见的DOM元素;

 DOM元素的几何属性变。

内容改变。

浏览器窗口尺寸改变。

获取某些属性

1、页面渲染初始化

每个页面至少需要一次回流,就是在页面第一次加载的时候。

2、添加或者删除可见的DOM元素

当DOM树的结构变化时,例如节点的增减、移动等,也会触发回流。浏览器引擎布局的过程,类似于树的前序遍历,是一个从上到下从左到右的过程。通常在这个过程中,当前元素不会再影响其前面已经遍历过的元素。

3、DOM元素的几何属性变化

当DOM元素的几何属性变化时,渲染树中的相关节点就会失效,浏览器会根据DOM元素的变化重建构建渲染树中失效的节点。当前元素的回流通常会带来一系列的反应,甚至触发整个文档的回流和重绘,性能代价是高昂的。

4、内容改变

文本改变或者图片大小改变而引起的计算值宽度和高度改变。

5、浏览器窗口尺寸改变

resize事件发生时。

6、获取某些属性

虽然浏览器引擎可能会针对回流做了优化,比如Opera,它会等到有足够数量的变化发生,或者等到一定的时间,或者等一个线程结束,再一起处理,这样就只发生一次回流。但除了render树的直接变化,当获取一些属性时,浏览器为取得正确的值也会触发回流。这些属性包括:offsetTop/tLeft/Width/Height、scrollTop/Left/Width/Height、 clientTop/Left/Width/Height、width、height,请求了getComputedStyle(), 或者 IE的 currentStyle也会引起回流。

4

减少回流、重绘其实就是需要减少对Render树的操作(合并多次多Dom和样式的修改),并减少对一些style信息的请求,尽量利用好浏览器的优化策略。具体方法有:

1、在内存中多次操作节点,完成后再添加到文档中去。

例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。

2、将那些改变样式的操作集合在一起,直接改变className。如果动态改变样式,则使用cssText。

栗🌰1:

js 代码:


var changeDiv = document.getElementById('changeDiv'); 
changeDiv.style.color = '#093'; 
changeDiv.style.background = '#eee'; 

可以合并为:

css 代码:


div.changeDiv {
    background: #eee;
    color: #093;
    height: 200px;
}

js 代码:


document.getElementById('changeDiv').className = ‘changeDiv’;

栗子🌰2:

js 代码:


// 不好的写法
var left = 1;
var top = 1;
el.style.left = left + "px";
el.style.top = top + "px";
// 比较好的写法
el.style.cssText += "; 
left: " + left + "px; 
top: " + top + “px;";

3、将需要多次重排的元素,脱离文档流。

position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。

4、尽量不要使用表格布局****。

如果没有定宽表格一列的宽度由最宽的一列决定,那么很可能在最后一行的宽度超出之前的列宽,引起整体回流造成table可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间。

6、让要操作的元素进行”离线处理”,处理完后一起更新。

a) 使用DocumentFragment进行缓存操作,引发一次回流和重绘;

b) 使用display:none,只引发两次回流和重绘;

c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;

** 7、在需要经常取那些引起浏览器重排的属性值时,要缓存到变量。**


// 别这样写
for(循环) {
    el.style.left = el.offsetLeft + 5 + "px";
    el.style.top = el.offsetTop + 5 + "px";
}
// 这样写好点
var left = el.offsetLeft,
top = el.offsetTop,
s = el.style; 
for (循环) { 
    left += 10; 
    top += 10; 
    s.left = left + "px"; 
    s.top = top + "px"; 
}

最后再强调一下,以上内容参考了网上的资料,如有雷同,那很正常。。。

始发于微信公众号: 前端麻辣烫

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 回流重绘


  转载请注明: 好好学java 回流重绘

 上一篇
JS数据类型的分类和判断 JS数据类型的分类和判断
     点击上方蓝色字体,关注我们 15 在前端笔试面试中“JS数据类型的分类和判断”是高频的基础考点,今天总结一下,对正在准备找工作的小伙伴应该有所帮助~ JavaScript中有6种数据类型:数字(number)、字符串(string
2021-04-05
下一篇 
页面的回流与重绘 页面的回流与重绘
前端面试中“页面的回流与重绘”是性能优化方面经常考察的一个知识点。今天总结一下,有不对或者不全面的地方欢迎指正~ 1 在讨论页面重绘、回流之前,需要对页面的呈现流程有些了解,页面是怎么把HTML结合CSS等显示到浏览器上的,下面的流程图显示
2021-04-05