我有以下代码块,需要尽快完成:

//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"

10-05 20:58
查看更多