- 浏览: 673886 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
zhouyicang:
为嘛人气不够,这么好的文章,我找了几十篇博客,才找到这篇解惑了 ...
HTML 块级元素/内联元素 -
young7:
不错,解惑了
HTML 块级元素/内联元素 -
lvjin948:
获取浏览器语言的完美方案。http://blog.csdn.n ...
JavaScript获取浏览器语言类型 -
tarena_hhh:
我用了css优化工具,发现他的顺序有很大不一样?????
CSS属性书写顺序及命名规则 -
deng131:
谢谢你的提醒,是有个地方写错了
javascript事件绑定addEventListener,attachEvent
转自:http://varnow.org/?p=232
参考:http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/
文本内容主要包括以下几点:
1. 什么是repaint/reflow?
2. 什么情况下会触发浏览器的repaint/reflow?
3. 浏览器自身所作的优化
4. 如何优化你的脚本来减少repaint/reflow?
一、什么是repaint/reflow?
页面在加载的过程中,需要对文档结构进行解析,同时需要结合各种各样的样式来计算这个页面长什么样子,最后再经过浏览器的渲染页面就出现了。这整个过程细说起来还是比较复杂,其中充满了repaint和reflow。对于DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式(浏览器的、开发人员定义的等)来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为reflow;当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器于是便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为repaint。
以上提到的只是在页面加载时必然会出现的repaint和reflow,除此之外,在页面加载完成后,用户的一些操作、脚本的一些操作都会导致浏览器发生这种行为,具体在后文阐述。
另外,关于浏览器渲染的更为详细的资料可以参考以下,涵盖了IE以及Firefox:
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow
二、什么情况下会触发浏览器的repaint/reflow?
除了页面在首次加载时必然要经历该过程之外,还有以下行为会触发这个行为:
* DOM元素的添加、修改(内容)、删除( Reflow + Repaint)
* 仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)
* 应用新的样式或者修改任何影响元素外观的属性
* Resize浏览器窗口、滚动页面
* 读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、 getComputedStyle()、currentStyle(in IE))
在继续下面的文章之前,先介绍一款强大的性能分析工具-dynaTrace,借助该功能能够清晰的得到页面中的资源消耗情况,从而对症下药。另外,更细节的方面是它可以跟踪每个函数调用所造成的CPU消耗、Repaint/Reflow。接下来就借助该工具来测试一下以上描述的几点情况。
DOM元素的增删改
先看代码
view plaincopy to clipboardprint?
1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3c.org/TR/html4/strict.dtd">
2. <html>
3. <body>
4. <div id="test1" onclick="addNode()">这里是第1个节点</div>
5. <div id="test2" onclick="modNode()">这里是第2个节点</div>
6. <div id="test3" onclick="delNode()">这里是第3个节点</div>
7. </body>
8. <script type="text/javascript">
9. function $(id){
10. return document.getElementById(id);
11. }
12. function addNode(){
13. var n = document.createElement('div');
14. n.innerHTML = 'New Node';
15. $('test1').appendChild(n);
16. }
17. function modNode(){
18. $('test2').innerHTML = 'hello';
19. }
20. function delNode(){
21. $('test3').parentNode.removeChild($('test3'));
22. }
23. </script>
24. </html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3c.org/TR/html4/strict.dtd">
<html>
<body>
<div id="test1" onclick="addNode()">这里是第1个节点</div>
<div id="test2" onclick="modNode()">这里是第2个节点</div>
<div id="test3" onclick="delNode()">这里是第3个节点</div>
</body>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
function addNode(){
var n = document.createElement('div');
n.innerHTML = 'New Node';
$('test1').appendChild(n);
}
function modNode(){
$('test2').innerHTML = 'hello';
}
function delNode(){
$('test3').parentNode.removeChild($('test3'));
}
</script>
</html>
在依次点击完每一个按钮后,我们来看看dynaTrace的情况,首先是一目了然的点击事件分布
image
放大之后来看一下每个事件的repaint/reflow情况:
增加节点:
image
修改节点:
image
删除节点:
image
图中的绿色部分表示的是reflow和repaint过程,其中比较短的绿条标示的reflow过程,后面长条部分表示的是repaint过程。从图中可以看出,对DOM节点的增删改都会造成reflow和repaint,由于改动小所以reflow消耗的时间很短,但是由于repaint是全局的,因此消耗的时间都比较长。
修改DOM元素前景色
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. n.style.color = 'red';
var n = $('colorNode');
n.style.color = 'red';
image
从上图中可以看到修改字体颜色后,浏览器只有repaint而没有reflow。接下来试试修改背景色:
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. n.style.backgroundColor = 'red';
var n = $('colorNode');
n.style.backgroundColor = 'red';
image
由图中可以看出,修改背景色也会造成reflow和repaint。另外,经过测试发现,只要是修改元素的cssText属性,不论它的值是什么,都会导致浏览器reflow和repaint,因此在某些时候选择特定的样式属性赋值会有更好的效果。
Resize浏览器窗口以及拖动滚动条
image
测试中的操作如下:缩小浏览器窗口->放大浏览器窗口->拖动页面滚动条至页面底部。从图中可以看到Resize浏览器窗口以及拖动滚动条都会造成浏览器的repaint,而且CPU的消耗也比较大,尤其是拖动滚动条的时候。
读取Layout属性
根据各种参考资料中的描述,在用Javascript读取DOM节点的Layout属性(offsetLeft、offsetTop、 offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left /Width/Height、getComputedStyle()、currentStyle(in IE)) 的时候也会触发repaint,不过在以下的测试例子中并没有发现这一点。
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. var temp = document.documentElement.currentStyle;
3. temp = n.offsetTop;
4. temp = n.offsetLeft;
5. temp = n.offsetWidth;
6. temp = n.offsetHeight;
7. temp = n.scrollTop;
8. temp = n.scrollHeight;
9. alert(temp);
var n = $('colorNode');
var temp = document.documentElement.currentStyle;
temp = n.offsetTop;
temp = n.offsetLeft;
temp = n.offsetWidth;
temp = n.offsetHeight;
temp = n.scrollTop;
temp = n.scrollHeight;
alert(temp);
image
三、浏览器优化
浏览器对于每一个渲染动作并不是立即执行,而是维护了一个渲染任务队列,浏览器会根据具体的需要分批集中执行其中的任务。除了浏览器自身维护的定期调度之外,脚本中的某些操作会导致浏览器立即执行渲染任务,例如读取元素的Layout属性。
view plaincopy to clipboardprint?
1. var bodystyle = document.body.style;
2. var computed;
3. if (document.body.currentStyle) {
4. computed = document.body.currentStyle;
5. } else {
6. computed = document.defaultView.getComputedStyle(document.body, '');
7. }
8.
9. //每次都读取
10.
11. bodystyle.color = 'red';
12. bodystyle.padding = '1px';
13. tmp = computed.backgroundColor;
14. bodystyle.color = 'white';
15. bodystyle.padding = '2px';
16. tmp = computed.backgroundImage;
17. bodystyle.color = 'green';
18. bodystyle.padding = '3px';
19. tmp = computed.backgroundAttachment;
20.
21. //最后再读取
22.
23. bodystyle.color = 'yellow';
24. bodystyle.padding = '4px';
25. bodystyle.color = 'pink';
26. bodystyle.padding = '5px';
27. bodystyle.color = 'blue';
28. bodystyle.padding = '6px';
29. tmp = computed.backgroundColor;
30. tmp = computed.backgroundImage;
31. tmp = computed.backgroundAttachment;
var bodystyle = document.body.style;
var computed;
if (document.body.currentStyle) {
computed = document.body.currentStyle;
} else {
computed = document.defaultView.getComputedStyle(document.body, '');
}
//每次都读取
bodystyle.color = 'red';
bodystyle.padding = '1px';
tmp = computed.backgroundColor;
bodystyle.color = 'white';
bodystyle.padding = '2px';
tmp = computed.backgroundImage;
bodystyle.color = 'green';
bodystyle.padding = '3px';
tmp = computed.backgroundAttachment;
//最后再读取
bodystyle.color = 'yellow';
bodystyle.padding = '4px';
bodystyle.color = 'pink';
bodystyle.padding = '5px';
bodystyle.color = 'blue';
bodystyle.padding = '6px';
tmp = computed.backgroundColor;
tmp = computed.backgroundImage;
tmp = computed.backgroundAttachment;
每次读取的渲染图:
image
最后读取的渲染图:
image
四、如何优化你的脚本来减少reflow/repaint?
1. 避免在document上直接进行频繁的DOM操作,如果确实需要可以采用off-document的方式进行,具体的方法包括但不完全包括以下几种:
(1). 先将元素从document中删除,完成修改后再把元素放回原来的位置
(2). 将元素的display设置为”none”,完成修改后再把display修改为原来的值
(3). 如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document
view plaincopy to clipboardprint?
1. function appendEveryTime(){
2. for( var i = 5000; i--; ){
3. var n = document.createElement('div');
4. n.innerHTML = 'node ' + i;
5. document.body.appendChild(n);/*每次创建的新节点都append到文档*/
6. }
7. }
8.
9. function appendLast(){
10. var frag = document.createDocumentFragment();
11. for( var i = 5000; i--; ){
12. var n = document.createElement('div');
13. n.innerHTML = 'node ' + i;
14. frag.appendChild(n);/*每次创建的节点先放入DocumentFragment中*/
15. }
16. document.body.appendChild(frag);
17. }
function appendEveryTime(){
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
document.body.appendChild(n);/*每次创建的新节点都append到文档*/
}
}
function appendLast(){
var frag = document.createDocumentFragment();
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
frag.appendChild(n);/*每次创建的节点先放入DocumentFragment中*/
}
document.body.appendChild(frag);
}
用dynaTrace观察的结果如下,appendLast的性能无论是在Javascript的执行时间以及浏览器渲染时间方面都优于 appendEveryTime。
appendEveryTime:
image
appendLast:
image
2. 集中修改样式
(1). 尽可能少的修改元素style上的属性
(2). 尽量通过修改className来修改样式
(3). 通过cssText属性来设置样式值
如下的代码中,每一次赋值都会造成浏览器重新渲染,可以采用cssText或者className的方式
view plaincopy to clipboardprint?
1. el.style.color = 'red;
2. el.style.height = '100px';
3. el.style.fontSize = '12px';
4. el.style.backgroundColor = 'white';
el.style.color = 'red;
el.style.height = '100px';
el.style.fontSize = '12px';
el.style.backgroundColor = 'white';
3. 缓存Layout属性值
对于Layout属性中非引用类型的值(数字型),如果需要多次访问则可以在一次访问时先存储到局部变量中,之后都使用局部变量,这样可以避免每次读取属性时造成浏览器的渲染。
view plaincopy to clipboardprint?
1. var width = el.offsetWidth;
2. var scrollLeft = el.scrollLeft;
var width = el.offsetWidth;
var scrollLeft = el.scrollLeft;
4. 设置元素的position为absolute或fixed
在元素的position为static和relative时,元素处于DOM树结构当中,当对元素的某个操作需要重新渲染时,浏览器会渲染整个页面。将元素的position设置为absolute和fixed可以使元素从DOM树结构中脱离出来独立的存在,而浏览器在需要渲染时只需要渲染该元素以及位于该元素下方的元素,从而在某种程度上缩短浏览器渲染时间,这在当今越来越多的Javascript动画方面尤其值得考虑。
view plaincopy to clipboardprint?
1. <body style="position:relative">
2. <div id="test" style="background-color:red;width:100px;position:relative;">Animation Here</div>
3. </body>
4. <script type="text/javascript">
5. function $(id){
6. return document.getElementById(id);
7. }
8. window.onload = function(){
9. var t = $('test');
10.
11. ~function(){
12. tt.style.left = t.offsetLeft + 5 + 'px';
13. tt.style.height = t.offsetHeight + 5 + 'px';
14. setTimeout(arguments.callee,500);
15. }();
16. }
17. </script>
<body style="position:relative">
<div id="test" style="background-color:red;width:100px;position:relative;">Animation Here</div>
</body>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
window.onload = function(){
var t = $('test');
~function(){
t.style.left = t.offsetLeft + 5 + 'px';
t.style.height = t.offsetHeight + 5 + 'px';
setTimeout(arguments.callee,500);
}();
}
</script>
通过修改#test元素的postion为relative和postion分别得到如下两个测试结果
position: relative
image
position: absolute
image
在postion:relative的测试当中,浏览器在重新渲染时做的工作比position:absolute多了不少。
参考资料
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow
EFFICIENT JAVASCRIPT
WEB优化reflow, repaint, 性能优化
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
参考:http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/
文本内容主要包括以下几点:
1. 什么是repaint/reflow?
2. 什么情况下会触发浏览器的repaint/reflow?
3. 浏览器自身所作的优化
4. 如何优化你的脚本来减少repaint/reflow?
一、什么是repaint/reflow?
页面在加载的过程中,需要对文档结构进行解析,同时需要结合各种各样的样式来计算这个页面长什么样子,最后再经过浏览器的渲染页面就出现了。这整个过程细说起来还是比较复杂,其中充满了repaint和reflow。对于DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式(浏览器的、开发人员定义的等)来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为reflow;当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器于是便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为repaint。
以上提到的只是在页面加载时必然会出现的repaint和reflow,除此之外,在页面加载完成后,用户的一些操作、脚本的一些操作都会导致浏览器发生这种行为,具体在后文阐述。
另外,关于浏览器渲染的更为详细的资料可以参考以下,涵盖了IE以及Firefox:
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow
二、什么情况下会触发浏览器的repaint/reflow?
除了页面在首次加载时必然要经历该过程之外,还有以下行为会触发这个行为:
* DOM元素的添加、修改(内容)、删除( Reflow + Repaint)
* 仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)
* 应用新的样式或者修改任何影响元素外观的属性
* Resize浏览器窗口、滚动页面
* 读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、 getComputedStyle()、currentStyle(in IE))
在继续下面的文章之前,先介绍一款强大的性能分析工具-dynaTrace,借助该功能能够清晰的得到页面中的资源消耗情况,从而对症下药。另外,更细节的方面是它可以跟踪每个函数调用所造成的CPU消耗、Repaint/Reflow。接下来就借助该工具来测试一下以上描述的几点情况。
DOM元素的增删改
先看代码
view plaincopy to clipboardprint?
1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3c.org/TR/html4/strict.dtd">
2. <html>
3. <body>
4. <div id="test1" onclick="addNode()">这里是第1个节点</div>
5. <div id="test2" onclick="modNode()">这里是第2个节点</div>
6. <div id="test3" onclick="delNode()">这里是第3个节点</div>
7. </body>
8. <script type="text/javascript">
9. function $(id){
10. return document.getElementById(id);
11. }
12. function addNode(){
13. var n = document.createElement('div');
14. n.innerHTML = 'New Node';
15. $('test1').appendChild(n);
16. }
17. function modNode(){
18. $('test2').innerHTML = 'hello';
19. }
20. function delNode(){
21. $('test3').parentNode.removeChild($('test3'));
22. }
23. </script>
24. </html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3c.org/TR/html4/strict.dtd">
<html>
<body>
<div id="test1" onclick="addNode()">这里是第1个节点</div>
<div id="test2" onclick="modNode()">这里是第2个节点</div>
<div id="test3" onclick="delNode()">这里是第3个节点</div>
</body>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
function addNode(){
var n = document.createElement('div');
n.innerHTML = 'New Node';
$('test1').appendChild(n);
}
function modNode(){
$('test2').innerHTML = 'hello';
}
function delNode(){
$('test3').parentNode.removeChild($('test3'));
}
</script>
</html>
在依次点击完每一个按钮后,我们来看看dynaTrace的情况,首先是一目了然的点击事件分布
image
放大之后来看一下每个事件的repaint/reflow情况:
增加节点:
image
修改节点:
image
删除节点:
image
图中的绿色部分表示的是reflow和repaint过程,其中比较短的绿条标示的reflow过程,后面长条部分表示的是repaint过程。从图中可以看出,对DOM节点的增删改都会造成reflow和repaint,由于改动小所以reflow消耗的时间很短,但是由于repaint是全局的,因此消耗的时间都比较长。
修改DOM元素前景色
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. n.style.color = 'red';
var n = $('colorNode');
n.style.color = 'red';
image
从上图中可以看到修改字体颜色后,浏览器只有repaint而没有reflow。接下来试试修改背景色:
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. n.style.backgroundColor = 'red';
var n = $('colorNode');
n.style.backgroundColor = 'red';
image
由图中可以看出,修改背景色也会造成reflow和repaint。另外,经过测试发现,只要是修改元素的cssText属性,不论它的值是什么,都会导致浏览器reflow和repaint,因此在某些时候选择特定的样式属性赋值会有更好的效果。
Resize浏览器窗口以及拖动滚动条
image
测试中的操作如下:缩小浏览器窗口->放大浏览器窗口->拖动页面滚动条至页面底部。从图中可以看到Resize浏览器窗口以及拖动滚动条都会造成浏览器的repaint,而且CPU的消耗也比较大,尤其是拖动滚动条的时候。
读取Layout属性
根据各种参考资料中的描述,在用Javascript读取DOM节点的Layout属性(offsetLeft、offsetTop、 offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left /Width/Height、getComputedStyle()、currentStyle(in IE)) 的时候也会触发repaint,不过在以下的测试例子中并没有发现这一点。
view plaincopy to clipboardprint?
1. var n = $('colorNode');
2. var temp = document.documentElement.currentStyle;
3. temp = n.offsetTop;
4. temp = n.offsetLeft;
5. temp = n.offsetWidth;
6. temp = n.offsetHeight;
7. temp = n.scrollTop;
8. temp = n.scrollHeight;
9. alert(temp);
var n = $('colorNode');
var temp = document.documentElement.currentStyle;
temp = n.offsetTop;
temp = n.offsetLeft;
temp = n.offsetWidth;
temp = n.offsetHeight;
temp = n.scrollTop;
temp = n.scrollHeight;
alert(temp);
image
三、浏览器优化
浏览器对于每一个渲染动作并不是立即执行,而是维护了一个渲染任务队列,浏览器会根据具体的需要分批集中执行其中的任务。除了浏览器自身维护的定期调度之外,脚本中的某些操作会导致浏览器立即执行渲染任务,例如读取元素的Layout属性。
view plaincopy to clipboardprint?
1. var bodystyle = document.body.style;
2. var computed;
3. if (document.body.currentStyle) {
4. computed = document.body.currentStyle;
5. } else {
6. computed = document.defaultView.getComputedStyle(document.body, '');
7. }
8.
9. //每次都读取
10.
11. bodystyle.color = 'red';
12. bodystyle.padding = '1px';
13. tmp = computed.backgroundColor;
14. bodystyle.color = 'white';
15. bodystyle.padding = '2px';
16. tmp = computed.backgroundImage;
17. bodystyle.color = 'green';
18. bodystyle.padding = '3px';
19. tmp = computed.backgroundAttachment;
20.
21. //最后再读取
22.
23. bodystyle.color = 'yellow';
24. bodystyle.padding = '4px';
25. bodystyle.color = 'pink';
26. bodystyle.padding = '5px';
27. bodystyle.color = 'blue';
28. bodystyle.padding = '6px';
29. tmp = computed.backgroundColor;
30. tmp = computed.backgroundImage;
31. tmp = computed.backgroundAttachment;
var bodystyle = document.body.style;
var computed;
if (document.body.currentStyle) {
computed = document.body.currentStyle;
} else {
computed = document.defaultView.getComputedStyle(document.body, '');
}
//每次都读取
bodystyle.color = 'red';
bodystyle.padding = '1px';
tmp = computed.backgroundColor;
bodystyle.color = 'white';
bodystyle.padding = '2px';
tmp = computed.backgroundImage;
bodystyle.color = 'green';
bodystyle.padding = '3px';
tmp = computed.backgroundAttachment;
//最后再读取
bodystyle.color = 'yellow';
bodystyle.padding = '4px';
bodystyle.color = 'pink';
bodystyle.padding = '5px';
bodystyle.color = 'blue';
bodystyle.padding = '6px';
tmp = computed.backgroundColor;
tmp = computed.backgroundImage;
tmp = computed.backgroundAttachment;
每次读取的渲染图:
image
最后读取的渲染图:
image
四、如何优化你的脚本来减少reflow/repaint?
1. 避免在document上直接进行频繁的DOM操作,如果确实需要可以采用off-document的方式进行,具体的方法包括但不完全包括以下几种:
(1). 先将元素从document中删除,完成修改后再把元素放回原来的位置
(2). 将元素的display设置为”none”,完成修改后再把display修改为原来的值
(3). 如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document
view plaincopy to clipboardprint?
1. function appendEveryTime(){
2. for( var i = 5000; i--; ){
3. var n = document.createElement('div');
4. n.innerHTML = 'node ' + i;
5. document.body.appendChild(n);/*每次创建的新节点都append到文档*/
6. }
7. }
8.
9. function appendLast(){
10. var frag = document.createDocumentFragment();
11. for( var i = 5000; i--; ){
12. var n = document.createElement('div');
13. n.innerHTML = 'node ' + i;
14. frag.appendChild(n);/*每次创建的节点先放入DocumentFragment中*/
15. }
16. document.body.appendChild(frag);
17. }
function appendEveryTime(){
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
document.body.appendChild(n);/*每次创建的新节点都append到文档*/
}
}
function appendLast(){
var frag = document.createDocumentFragment();
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
frag.appendChild(n);/*每次创建的节点先放入DocumentFragment中*/
}
document.body.appendChild(frag);
}
用dynaTrace观察的结果如下,appendLast的性能无论是在Javascript的执行时间以及浏览器渲染时间方面都优于 appendEveryTime。
appendEveryTime:
image
appendLast:
image
2. 集中修改样式
(1). 尽可能少的修改元素style上的属性
(2). 尽量通过修改className来修改样式
(3). 通过cssText属性来设置样式值
如下的代码中,每一次赋值都会造成浏览器重新渲染,可以采用cssText或者className的方式
view plaincopy to clipboardprint?
1. el.style.color = 'red;
2. el.style.height = '100px';
3. el.style.fontSize = '12px';
4. el.style.backgroundColor = 'white';
el.style.color = 'red;
el.style.height = '100px';
el.style.fontSize = '12px';
el.style.backgroundColor = 'white';
3. 缓存Layout属性值
对于Layout属性中非引用类型的值(数字型),如果需要多次访问则可以在一次访问时先存储到局部变量中,之后都使用局部变量,这样可以避免每次读取属性时造成浏览器的渲染。
view plaincopy to clipboardprint?
1. var width = el.offsetWidth;
2. var scrollLeft = el.scrollLeft;
var width = el.offsetWidth;
var scrollLeft = el.scrollLeft;
4. 设置元素的position为absolute或fixed
在元素的position为static和relative时,元素处于DOM树结构当中,当对元素的某个操作需要重新渲染时,浏览器会渲染整个页面。将元素的position设置为absolute和fixed可以使元素从DOM树结构中脱离出来独立的存在,而浏览器在需要渲染时只需要渲染该元素以及位于该元素下方的元素,从而在某种程度上缩短浏览器渲染时间,这在当今越来越多的Javascript动画方面尤其值得考虑。
view plaincopy to clipboardprint?
1. <body style="position:relative">
2. <div id="test" style="background-color:red;width:100px;position:relative;">Animation Here</div>
3. </body>
4. <script type="text/javascript">
5. function $(id){
6. return document.getElementById(id);
7. }
8. window.onload = function(){
9. var t = $('test');
10.
11. ~function(){
12. tt.style.left = t.offsetLeft + 5 + 'px';
13. tt.style.height = t.offsetHeight + 5 + 'px';
14. setTimeout(arguments.callee,500);
15. }();
16. }
17. </script>
<body style="position:relative">
<div id="test" style="background-color:red;width:100px;position:relative;">Animation Here</div>
</body>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
window.onload = function(){
var t = $('test');
~function(){
t.style.left = t.offsetLeft + 5 + 'px';
t.style.height = t.offsetHeight + 5 + 'px';
setTimeout(arguments.callee,500);
}();
}
</script>
通过修改#test元素的postion为relative和postion分别得到如下两个测试结果
position: relative
image
position: absolute
image
在postion:relative的测试当中,浏览器在重新渲染时做的工作比position:absolute多了不少。
参考资料
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow
EFFICIENT JAVASCRIPT
WEB优化reflow, repaint, 性能优化
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
发表评论
-
IE浏览器stylesheets加载资源限制问题
2015-03-08 20:30 1073@import url()做一下总结: 1:@import ... -
理解Javascript原型及继承
2012-08-15 22:13 1347js初次使用起来觉得很简单但是在使用一段时间后很不深入的理解原 ... -
JS判断IE浏览器支持版本
2012-02-01 19:00 2969/* * @description 判断是否是IE,返回具体 ... -
jsonp动态创建script方式IE9问题
2012-02-01 16:28 2385在IE9浏览器创建一个script元素,然后指定其src属性u ... -
IE9下使用jsonp方式调用问题
2012-01-31 19:03 22931. 如果JSONP返回的Content-Type不符合规范, ... -
JavaScript获取浏览器语言类型
2011-12-31 18:24 7808获取浏览器语言: IE: navigator.browser ... -
IE Security Comprehensive Protection
2011-12-19 20:14 1767IE浏览器安全方面的处理,本人英文不好建议大家直接看英文: ... -
javaScript 中比较数字字符串问题
2011-10-10 21:49 4676在实现前端页面排序功能过程中遇到的问题,由于自己的粗心导致了生 ... -
javascript设置label标签 for属性
2011-09-11 10:36 3609js创建label标签的for属性用来增加操作响应区域。 v ... -
javascript事件绑定addEventListener,attachEvent
2011-07-31 18:55 3525为了考虑浏览器的兼容性问题,都需要对浏览器进行类型检测。 f ... -
readyState五种状态详解
2011-07-24 14:15 1616(0) UNINITIALIZED 未初始化 The obje ... -
getElementByTagName 与 querySelectorAll
2011-07-14 11:29 1480虽然网上有中文翻译但是还是直接看英文有感觉。getElemen ... -
拖放 Drag and drop 方法
2011-07-10 18:55 1528虽然网上又很多实现方法,但是还是需要理解拖放原理。通过绑定on ... -
闭包传入参数 window & undefined
2011-07-03 08:53 2307大家在前端开发中对闭包应该和熟悉了,也就是几种常见的闭包方式: ... -
textarea光标位置插入文字
2011-06-18 18:14 2130各浏览器TextArea获得焦点后的光标位置情况: text ... -
IE6上Array不支持indexOf方法
2011-06-06 10:17 2253在IE6不支持Array上indexOf方法,又是可恶的ie, ... -
处理不支持JavaScript脚本情况
2011-05-26 10:24 1340现在主流的浏览器都支持javascrip, 但还是有小部分不支 ... -
动态创建iframe设置属性name问题
2011-04-20 13:54 2734通常iframe的name可以是link或者form的targ ... -
WebSocket and Socket.IO
2011-04-06 15:39 3465WebSocket API是下一代客户端-服务器的异步通信方法 ... -
Preload CSS/JavaScript预加载
2011-04-06 10:20 1475希望达到效果是页面第一次载入以后,如果在次刷新页或者进入下一个 ...
相关推荐
总的来说,理解`reflow`和`repaint`的原理,并通过优化DOM操作、样式修改、缓存属性和利用定位属性等方式,可以有效地减少浏览器的渲染负担,提高网页性能。在实际开发中,开发者应当养成良好的编程习惯,时刻关注...
你是不是经常听师兄或一些前端前辈说不能用CSS通配符 *...1.什么是Repaint/Reflow? 好,先上一张图:浏览器解析大概的工作流程 这张图应该可以很好理解,归纳为四个步骤: 1、解析HTML以构建DOM树:渲染引擎开始解析H
**如何避免或减少Repaint和Reflow:** 1. **离线操作**:先移除元素,完成修改后再放回,减少对页面的影响。 2. **隐藏元素**:通过设置`display: none`,修改后再恢复,避免实时计算布局。 3. **使用...
1. 浏览器渲染机制 2. 重绘 3. 回流 4. 浏览器优化 5. 减少重绘与回流
浏览器渲染优化策略包括减少 repaint 和 reflow、合理使用缓存、使用 CSS 动画、避免过多的 DOM 操作、使用 lazy loading 等。这些策略可以减少浏览器的渲染时间,提高浏览器的性能和用户体验。 在浏览器渲染过程中...
在前端性能优化的领域中,回流(Reflow)与重绘(Repaint)是非常关键的概念。它们是浏览器渲染过程中最常见、也最影响性能的两个步骤。为了深入理解这两个概念,我们首先需要了解浏览器的渲染流程。 在用户通过...
reflow和repaint是浏览器渲染过程中的重要环节,频繁的reflow会显著降低页面性能。因此,优化页面渲染的关键在于减少不必要的reflow。例如,为图片预先设定宽度和高度可以避免图片加载后引起的布局变化。此外,尽量...
2. 正确理解Repaint和Reflow Repaint(重绘)是指元素外观变化但不影响布局时发生的情况,例如改变颜色或边框。Reflow(重排)则是布局或几何属性发生变化时,浏览器需要重新计算元素及关联元素的布局。频繁的Reflow...
这些过程通常被称为重排(Reflow)和重绘(Repaint),过多的重排和重绘会导致性能下降,因此应尽量避免不必要的操作。 性能优化可以从多个角度进行。例如,利用CSS的`display: none`或`visibility: hidden`来隐藏...
浏览器的渲染过程涉及多个步骤,包括解析HTML、CSS、JavaScript以及处理图片等资源,其中关键环节是页面的渲染、重绘(repaint)和...在实际开发中,应尽可能减少reflow和repaint的次数,以优化页面加载和交互速度。
本视频主打内容最全最新,包括大前端基础与高频面试题,打造一站式知识长龙 服务,适合有前端基础的同学学习...2.如何最小化重绘(repaint)和回流(reflow)?3.Javascript作用域链? 4.数据请求 5.跨域和同源策略6.面向对象
- 解析过程中,CSS和HTML可以并行加载,但JS执行会阻塞HTML解析,防止页面布局频繁变化(repaint和reflow)。 - 浏览器根据渲染树进行布局计算,确定每个节点的位置和大小,然后绘制到屏幕上,最终展示给用户。 ...
在布局计算完成后,浏览器会进行回流(reflow)和重绘(repaint)两个重要步骤。回流指的是浏览器为了确定元素的位置和尺寸而进行的计算过程,这通常是在初次加载页面或进行DOM操作时发生。重绘则是当元素样式改变但...
- **减少重排(Reflow)和重绘(Repaint):** 重排和重绘是浏览器渲染过程中的两个关键性能消耗点。重排是当元素的布局改变时发生的,而重绘是当元素的样式改变(不涉及布局变化)时发生的。开发者应当尽量避免这两...
- **渲染优化**:减少重排(reflow)和重绘(repaint),避免不必要的DOM操作。 - **JavaScript优化**:合理使用异步加载,避免阻塞页面渲染,利用闭包和作用域控制变量。 - **资源加载**:利用CDN加速,合并和...
Repaint 和 Reflow Repaint 是指浏览器重新绘制某个元素的过程,通常发生在元素的外观被改变时。Reflow 是指浏览器重新计算 Render Tree 的过程,通常发生在元素的布局被改变时。 display 属性的其他值 除了 none...
导致js效率低的两个因素都包括在内了在频繁的操作DOM和CSS时,浏览器会不停的执行重排和重绘,在PC版本的浏览器中,因为浏览器可用的内存比较大,用户肉眼几乎看不见页面动画产生的repaint和reflow,所以工程师几乎...
这个过程就包括了`repaint`和相关的概念,如`reflow`。 **重涂(Repaint)**: 重涂是指元素的视觉属性发生变化但其几何尺寸(宽度、高度)保持不变时,浏览器只需重新绘制该元素的新外观,而无需调整周围元素的...