我有以下代码块,需要尽快完成:
//someSpans is an array of spans, with each span containing two child spans inside of it
$.each( someSpans, function (i, span) {
//Get the span widths, then add them to the style to make them permanent
var aSpan = span.children[0];
var bSpan = span.children[1];
span.style.width = (aSpan.offsetWidth + bSpan.offsetWidth) + 'px';
aSpan.style.width = aSpan.offsetWidth + 'px';
bSpan.style.width = bSpan.offsetWidth + 'px';
});
如果someSpans是一个包含1000个对象的数组,则上面显示的此循环将导致3000次浏览器重绘,即使屏幕上的任何内容实际上都没有改变,因为样式中的新“ width”属性与现有的“ auto”宽度匹配。有没有一种方法可以防止浏览器在循环结束之前重绘CSS?我觉得这将大大减少完成循环所需的时间。
我觉得requestAnimationFrame可能是完成我要寻找的东西的关键,但也许我不在基地。
最佳答案
尽管有关为什么的评论很有意义,但这是一个更好的答案。
问题的一部分是样式的交替读取/写入。即,设置span.style.width
现在使aSpan.offsetWidth
为“脏”,并且必须呈现CSS。但是,请考虑以下事项:
var aWidth = aSpan.offsetWidth;
var bWidth = bSpan.offsetWidth;
span.style.width = (aWidth + bWidth) + 'px';
aSpan.style.width = aWidth + 'px';
bSpan.style.width = bWidth + 'px';
现在,每个循环将渲染缩减为一次。更具体地说,是在下一次迭代中读取
offsetWidth
导致渲染。练习:虽然它可以使代码变得更加晦涩难懂,但有时却不必要,因此,我有时编写了这样的代码来循环两次。第一次将操作收集到一个数组中,第二次循环能够组合所有“设置”操作,而无需访问任何布局值。
MSDN有一些很棒的documents on JavaScript performance,在这里最适用的是"Managing layout efficiently"