注意:回流必定会触发重绘,而重绘不必定会回流javascript
渲染树发生变化,就会产生回流或重绘,例如:php
display:none
(回流和重绘都会触发),visibility: hidden
(只有重绘,由于没有几何变化)再看一些例子:css
var bstyle = document.body.style;
bstyle.padding = "20px"; // 回流,重绘
bstyle.border = "10px solid red"; // 再一次回流和重绘
bstyle.color = "blue"; // 只有重绘,没有颜色变化
bstyle.backgroundColor = "#fad"; // 重绘
bstyle.fontSize = "2em"; // 回流,重绘
// 新加元素 - 回流,重绘
document.body.appendChild(document.createTextNode('dude!'));
复制代码
还有些回流会带来更多的性能损耗,好比你把页面顶部的一个div设置了动画或者拉大了,致使页面下面其余部分都下去了。java
由于渲染树的回流和重绘比较损耗,浏览器目标在于减少负面影响。一个策略就是根本不作这件事情,至少如今不作。浏览器把你写的更改放在一个队列里而后批量执行。用这种方法将会把屡次须要回流的更改合成一次回流进行计算。浏览器可以把屡次更改放进队列,而后隔一段时间或者达到必定数量时一次性处理掉。git
可是有时候,脚本(js)可能会阻止浏览器这项优化措施,致使它(立刻)清理队列以及执行全部更改。这件事发生在你修改样式信息,好比:github
offsetTop
, offsetLeft
, offsetWidth
, offsetHeight
scrollTop
/Left/Width/HeightclientTop
/Left/Width/HeightgetComputedStyle()
, 或者 currentStyle
in IE以上这些主要是获取某个节点的样式信息的,一旦你调用这些,浏览器都须要给你最新的值。为了这样作,浏览器就须要执行全部计划中的更改,清理队列执行回流。浏览器
举个例子,快速连续地获取和设置样式(循环中),好比:app
// no-no!
el.style.left = el.offsetLeft + 10 + "px";
复制代码
几条建议以下:oop
cssText
去作。// bad
var left = 10,
top = 10;
el.style.left = left + "px";
el.style.top = top + "px";
// better
el.className += " theclassname";
// 或者须要动态的修改top和left...
// better
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
复制代码
以“离线”方式批量处理DOM更改。离线意思是不在真实的DOM树下(作更改),你能够:性能
documentFragment
去临时存一下更改display:none
(须要一次回流及重绘)隐藏掉元素,增长100次修改,而后再显示(再花费一次回流重绘)。这样你就拿2次回流和重绘换掉了100次。不要过度地使用computed styles。若是你须要使用,那就拿一次,而后保存到本地变量里,并对这个本地变量进行操做。从新看下那个no-no例子:
// no-no!
for(big; loop; here) {
el.style.left = el.offsetLeft + 10 + "px";
el.style.top = el.offsetTop + 10 + "px";
}
// better
var left = el.offsetLeft,
top = el.offsetTop
esty = el.style;
for(big; loop; here) {
left += 10;
top += 10;
esty.left = left + "px";
esty.top = top + "px";
}
复制代码