重新计算风格:为什么如此口吃?

rai*_*7ow 8 javascript css performance google-chrome

假设我们有一个代码将一系列类似的元素注入到DOM中.像这样的东西:

var COUNT = 10000,
    elements = Object.keys(Array(COUNT).join('|').split('|'));

var d = document, 
    root = d.getElementById('root');

function inject() {
    var count = COUNT,
        ul     = d.createElement('ul'),
        liTmpl = d.createElement('li'),
        liEl   = null;

    console.time('Processing elements');
    while (count--) {
        liEl = liTmpl.cloneNode(false);
        liEl.textContent = elements[count];
        ul.appendChild(liEl);
    }
    console.timeEnd('Processing elements');

    console.time('Appending into DOM');
    root.appendChild(ul);
    console.timeEnd('Appending into DOM');
};
d.getElementById('inject').addEventListener('click', inject);
Run Code Online (Sandbox Code Playgroud)

演示.

当这个片段在Firefox(25.0)中运行时,调用'inject'和实际看到它的结果更多-o-less之间的时间对应于记录的内容time/timeEnd.对于1000个元素,大约4毫秒; 10000,约40等.很正常,不是吗?

然而,Chrome(30.0和Canary 32.0已经过测试)并非如此.虽然报告的处理和追加时间实际上少于Firefox,但这些元素的渲染需要更多.

困惑的是,我已经针对不同的场景检查了Chrome的分析器 - 事实证明,瓶颈在于Recalculate Style动作.10000个节点需要2-3秒,20000个节点需要8秒,30000个节点需要17秒.


现在真正的问题是:有没有人处于相同的情况,是否有任何解决方法?

我们想到的一种可能的方法是将这些节点的可见性限制在一种惰性负载中('某种',因为它更多的是'懒惰显示':元素已经到位,只有它们的可见性将是有限).已经证实,只有当元素即将变得可见时才会触发"重新计算样式"(实际上这是有意义的).

Gab*_*oli 9

看起来问题在于具有的li元素display:list-item

如果不是ul/ li你使用div元素,它在chrome中工作得相当快..

还创建了一个li{display:block;}修复延迟的css规则.

并且手动添加list-item显示延迟,即使元素已经在DOM中呈现(它们必须重新渲染)

请参阅http://jsfiddle.net/6D7sM/1/上的演示

(所以看起来渲染display:list-item元素的铬很慢)


还有一个相关错误提交到Chrome http://code.google.com/p/chromium/issues/detail?id=71305已合并到http://code.google.com/p/chromium/issues/detail?id =%2094248(看起来在早期版本中它崩溃了chrome,但它已被修复.崩溃,而不是速度)