当浏览器下载完所有页面HTML 标记,JavaScript,CSS,图片之后,它解析文件并创建两个内部数据结构:
一旦 DOM 树和渲染树构造完毕,浏览器就可以显示(绘制)页面上的元素了。
当 DOM 改变影响到元素的几何属性(宽和高)——例如改变了边框宽度或在段落中添加文字,将发生
一系列后续动作——浏览器需要重新计算元素的几何属性,而且其他元素的几何属性和位置也会因此改变受到影响。浏览器使渲染树上受到影响的部分失效,然后重构渲染树。这个过程被称作重排版。重排版完成时,浏览器在一个重绘进程中重新绘制屏幕上受影响的部分。
不是所有的 DOM 改变都会影响几何属性。例如,改变一个元素的背景颜色不会影响它的宽度或高度。在这种情况下,只需要重绘(不需要重排版),因为元素的布局没有改变。
重绘和重排版是负担很重的操作,可能导致网页应用的用户界面失去相应。所以,十分有必要尽可能减少这类事情的发生。
正如前面所提到的,当布局和几何改变时需要重排版。在下述情况中会发生重排版:
根据改变的性质,渲染树上或大或小的一部分需要重新计算。某些改变可导致重排版整个页面:例如,当一个滚动条出现时。
因为计算量与每次重排版有关,大多数浏览器通过队列化修改和批量显示优化重排版过程。然而,你可能(经常不由自主地)强迫队列刷新并要求所有计划改变的部分立刻应用。获取布局信息的操作将导致刷新队列动作,这意味着使用了下面这些方法:
在改变样式的过程中,最好不要使用前面列出的那些属性。任何一个访问都将刷新渲染队列,即使你正在获取那些最近未发生改变的或者与最新的改变无关的布局信息。
重排版和重绘代价昂贵,所以,提高程序响应速度一个好策略是减少此类操作发生的机会。为减少发生次数,你应该将多个 DOM 和风格改变合并到一个批次中一次性执行。
var el = document.getElementById('mydiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';
这里改变了三个风格属性,每次改变都影响到元素的几何属性。在这个糟糕的例子中,它导致浏览器重排版了三次。大多数现代浏览器优化了这种情况只进行一次重排版。
一个达到同样效果而效率更高的方法是:将所有改变合并在一起执行,只修改 DOM一次。可通过使用 cssText 属性实现:
var el = document.getElementById('mydiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
另一个一次性改变风格的办法是修改 CSS 的类名称,而不是修改内联风格代码。这种方法适用于那些风格不依赖于运行逻辑,不需要计算的情况。改变CSS 类名称更清晰,更易于维护;
推荐尽可能使用文档片断因为它涉及最少数量的 DOM 操作和重排版。
浏览器通过队列化修改和批量运行的方法,尽量减少重排版次数。当你查询布局信息如偏移量、滚动条位置,或风格属性时,浏览器刷队列并执行所有修改操作,以返回最新的数值。最好是尽量减少对布局信息的查询次数,查询时将它赋给局部变量,并用局部变量参与计算。
显示和隐藏部分页面构成展开/折叠动画是一种常见的交互模式。它通常包括区域扩大的几何动画,将页面其他部分推向下方。
使用以下步骤可以避免对大部分页面进行重排版:
事件逐层冒泡总能被父元素捕获。采用事件委托技术之后,你只需要在一个包装元素上绑定事件,用于处理子元素发生的所有事件。

