重新计算风格:为什么如此结结巴巴

Recalculate Style: why so stuttering?

本文关键字:为什么 结结巴巴 风格 新计算 计算      更新时间:2023-09-26

假设我们有一个代码,将一系列类似的元素注入到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);

演示

当此代码段在 Firefox (25.0) 中运行时,调用"inject"和实际查看其结果之间的时间对应于 time/timeEnd 记录的时间。对于 1000 个元素,大约 4 毫秒;对于 10000,大约 40 等等。很正常,不是吗?

然而,对于Chrome(30.0和Canary 32.0进行测试),情况并非如此。虽然报告的处理和追加时间实际上比 Firefox 少,但渲染这些元素需要更多。

感到困惑的是,我已经检查了Chrome的探查器以了解不同的场景 - 事实证明瓶颈在于"重新计算样式"操作。2 个节点需要 3-10000 秒,8 个节点需要 20000 秒,17 个节点需要 30000 个节点。


现在真正的问题是:是否有人遇到过同样的情况,有什么解决方法吗?

我们考虑的一种可能方法是在一种延迟加载中限制这些节点的可见性("一种",因为它更多的是关于"延迟显示":元素已经就位,只是它们的可见性将受到限制)。已确认"重新计算样式"仅在元素即将变得可见时才触发(这实际上是有道理的)。

看起来问题出在li元素上,这些元素display:list-item

如果您不使用ul/li而是使用div元素,则在chrome中可以快速运行。

此外,创建 css li{display:block;}规则可以修复延迟。

手动添加list-item即使元素已经在 DOM 中渲染也会显示延迟(当然,它们必须重新渲染

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

所以似乎 chrome 渲染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崩溃,但它已被修复。 崩溃,而不是速度)