1.重排和重绘
1.1 浏览器的运行机制
构建DOM树
:渲染引擎解析HTML
文档,首先将标签转换成DOM
树中的DOM node
(包含js生成的标签)生成DOM树;构建渲染树
:解析对应的CSS样式文件信息(包含js生成的样式和外部css文件),而这些文件信息以及html中可见的指令,构建渲染树;渲染树中每个Node节点都有自己的style,而且渲染树不包含隐藏的节点,因为这些节点不会用于呈现;- 布局渲染树:从根节点递归调用,计算每一个元素的大小、位置等,给每个节点所应该在屏幕上呈现的精确坐标;
- 绘制渲染树:遍历渲染树,使用UI层来绘制每个节点。
1.2重绘
当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定之后,浏览器便将这些元素按照各自的特性绘制一遍,将内容呈现在页面上。
重绘是指一个元素外观的改变触发的浏览器行为,浏览器会根据元素的新属性重新绘制,是元素呈现新的外观。
触发重绘的条件:改变元素外观属性,如:color、background-color等。
注意:table及其内部元素可能需要多次计算才能确定其在渲染树中节点的属性值,比通道能元素要多花费两倍事件,因此要尽量避免使用table布局页面。
1.3重排 (回流/重构)
当渲染树中的一部分(或全部)因为元素的"规模尺寸、布局、隐藏等改变而需要重新构建,这就称为回流。"每个页面至少需要一次回流,就是在页面第一次加载的时候。
1.4重绘和重排的区别
在回流的时候,浏览器会使得渲染树中受到的影响部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕上,该过程称为重绘。
触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如:
- 页面渲染初始化
- 添加和删除DOM元素
- 元素位置的改变、或者使用动画
- 元素尺寸的改变–大小、外边距、边框
- 浏览器窗口尺寸的改变
- 填充内容发生的改变
- 读取某些元素属性(页面高宽、滚动距离等)
1.5优化
(1)浏览器自己的优化:浏览器会维护一个队列,吧所有会引起回流、重绘的操作放入这个队列中,等队列中的操作到了一定的数量或者到了一定的事件间隔的,浏览器会刷新队列,进行一个批处理。这样就能让多次的回流、重绘变成一次回流重绘。
(2)我们的优化:要减少重排和重绘就是要减少对渲染树的操作,则可以合并多次DOM和样式的修改,并减少对style样式的请求
- 直接改变元素的className
display:none;
先设置元素为display:none;
,然后进行页面布局操作;设置完成后将元素设置为display:block;
这样的话就只引发两次重绘和重排- 使用cloneNode(true or false)和replaceChild技术,引发一次重绘或重排
- 将需要多次重排的元素,position属性设置为absolute或fixed,元素脱离了文档流,他的变化不会影响到其他的元素
- 如果需要创建多个DOM元素节点,可以使用DocumentFragment创建完一次性的加入dcument
<ul class="main">
</ul>
<script>
// 不要边创建边渲染
let fragment = document.createDocumentFragment();
for(let i = 0; i < 1000; i++){
let li = document.createElement("li");
li.innerHTML = "apple" + i;
fragment.appendChild(li)
}
document.querySelector(".main").appendChild(fragment)
</script>