浏览器下载页面上的所有内容:HTML、JavaScript、CSS、图片——然后解析生成两个内部数据结构:DOM树:表示页面结构Rendering树:表示如何显示DOM节点DOM树中每一个需要显示的节点在渲染树中至少有一个对应的节点(隐藏的DOM元素在渲染树中没有对应的节点)。渲染树中的节点称为“框架”或“框”,将页面元素理解为具有填充、边距、边框和位置的框。一旦构建了DOM树和渲染树,浏览器就开始显示(绘制)页面元素。当DOM的变化影响了元素的几何属性(比如宽度和高度)时——浏览器需要重新计算元素的几何属性,等等元素的几何属性和位置也会受此影响。浏览器使渲染树受影响的部分无效并重建渲染树。这个过程称为回流。回流完成后,浏览器会将受影响的部分重新绘制到屏幕上。这个过程称为重绘(repaint)。重绘和回流操作都是开销很大的操作,它们会导致Web应用程序的UI无响应,因此应尽可能减少此类过程的发生。回流的原因添加或删除可见的DOM元素元素位置更改元素大小更改内容更改(例如:文本更改或图像被另一个不同大小的图像替换)页面渲染初始化浏览器窗口大小更改渲染树更改排队刷新到期对于每次重排的计算成本,大多数浏览器通过排队修改和批量执行(将多个重排过程合并为一个)来优化重排过程。但是,某些操作会强制刷新队列并要求立即执行队列的重新排序(从而破坏浏览器的优化策略)。获取布局信息的操作会造成强制刷新队列,让浏览器不得不在渲染队列中执行“pendingchanges”并触发重排返回正确的值,scrollHeightclientTop,clientLeft,clientWidth,clientHeightgetComputedStyle()优化方法:尽量不要在布局信息发生变化时查询,等布局信息发生变化后再查询,尽量减少重绘和重排重绘和重排的代价是非常昂贵的,所以一个提高程序响应能力的好策略就是减少此类操作的发生。为了减少出现的次数,应该合并对DOM和样式的多次修改,然后一次性处理。合并多个样式修改varel=document.getElementById('myDiv')el.style.borderLeft='1px'el.style.borderRight='2px'el.style.padding='5px'在上面的例子中,有两个问题:style属性的每一次变化都会影响元素的集合结构,最坏的情况下,会导致浏览器触发三次重排(大多数现代浏览器都为此进行了优化,只触发一次重排)以上代码访问4次DOM优化方法:使用cssText属性,合并所有修改后处理varel=document.getElementById('myDiv')el.style.cssText+='border-left:1px;边框-右:2px;填充:5px;';批量修改DOM当需要对DOM元素进行一系列操作时,可以使用以下步骤减少重绘和重排次数,使元素脱离文档流,对其进行一些操作的方法带来元素返回到文档中,使元素脱离文档流:隐藏元素,应用修改,然后重新显示它。使用documentfragment在当前DOM外建一个子树,然后复制到document中,将element元素复制到另一个不在document中的子树。节点,修改副本,然后在完成后替换原始元素。上面的介绍中提到了缓存布局信息。浏览器通过排队修改和批量执行来减少重排的次数。但是当查询布局信息(例如获取偏移量、滚动位置、计算的样式值)时,浏览器会刷新队列并应用所有更改以返回最新值。因此,最好的做法应该是尽量减少布局信息的获取次数,获取后复制到一个局部变量中,再对局部变量进行操作。IE和:hover避免在大量元素上使用:hover的效果
