发表于2014-11-24 14:48:19
要谈Reflow(重排)和Reprint(重绘)总是离不开浏览器解析网页的原理,可以先看下这篇文章:《How browsers work》(中文翻译版,陈浩压缩版)了解下浏览器在背后都做了些什么。
浏览器由很多组件构成,他们都有不同的分工,协同工作把网页渲染出来。其中呈现引擎(Webkit)和Javascript解释器(V8)是我们今天所关注的重点。呈现引擎会尽可能快的完成:把HTML解析为DOM树(同时解析CSS)→同时构造呈现树(Render tree)→布局(Layout)→绘制(Paint)。
其中解析的算法是相当复杂的(尤其对于HTML,因为它的容错性很高),引擎会根据W3C的相关规定,在通过涉及词法分析、语法分析、自动生成解析器、编译等一系列高大上的东西后完成对DOM树的构建。呈现器知道如何通过很多规则和计算来进行布局并将自身及其子元素绘制出来。我们先暂停下,因为到这里有很多需要注意的地方:
到目前为止呈现引擎已经完成了前两个步骤,接下来就是并不轻松的布局了。呈现器在创建完成并添加到呈现树时,并不包含位置和大小信息。计算这些值的过程称为布局(Layout)或称为重排(Reflow)。至此Reflow终于现身了。现代浏览器对重排的处理越来越机智,为避免对所有细小更改都进行整体布局,浏览器采用了一种“dirty 位”系统,它会尽可能的利用缓存来减少或用队列分批进行重排。布局分为全局布局(同步)和增量布局(异步),如果更改网页字体大小或是调整窗口大小都会触发全局布局,而类似插入DOM、请求某些样式信息等需要重新计算位置和大小的操作会触发增量布局。
最后进入绘制阶段,系统会遍历呈现树,并调用呈现器的paint方法,将呈现器的内容显示在屏幕上。绘制工作是使用用户界面基础组件完成的。绘制也同样分为全局绘制和增量绘制。系统很巧妙的将多个区域合并成一个。绘制的顺序为:轮廓→子代→边框→背景图片→背景颜色。当有类似颜色改变这样的操作发生后会触发重新绘制(Reprint),它的开销比起重排小很多,在发生变化时,浏览器会尽可能做出最小的响应。
下面是利用Firefox对维基百科页面渲染的可视化视频。
在了解完浏览器渲染页面的原理后,我们很容易总结出几种可以触发重排的操作:
Chrome中的DevTools可以很方便的观察重排和重绘。如果你对Chrome DevTools还不太熟悉可以参考Google官方文档和这篇文章进行了解。
重排和重绘在实际开发中不可避免,我们只能尽量减少重排和重绘的次数,降低浏览器渲染网页的开销,以此带来的性能提升在移动平台上效果显著。
例:
//修改CSS类名而不是逐条修改属性 function changeStyle(element,className) { element.className = className; } //借助DocumentFragment function CreateFragments(){ var fragment = document.createDocumentFragment(); for(var i = 0;i < 10000;i++){ var tmpNode = document.createElement("div"); tmpNode.innerHTML = "test" + i; fragment.appendChild(tmpNode); } document.body.appendChild(fragment); }
原文地址:http://yangjian.me/learning/reflow-and-reprint-in-browsers/
参考资料