假设我们有一个将一系列相似元素注入 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 ms;10000,大约 40 等等。很正常,不是吗?
然而,对于 Chrome(30.0 和 Canary 32.0 已测试),情况并非如此。虽然报告的处理和附加时间实际上少于 Firefox,但渲染这些元素需要更多时间。
困惑的是,我检查了 Chrome 的分析器是否有不同的场景——结果发现瓶颈在于重新计算样式操作。10000 个节点需要 2-3 秒,20000 个节点需要 8 秒,30000 个节点需要 17 秒。
现在真正的问题是:有没有人遇到过同样的情况,有什么解决方法吗?
我们考虑过的一种可能的方法是将这些节点的可见性限制在一种延迟加载中(“一种”,因为它更多的是关于“延迟显示”:元素已经到位,只有它们的可见性是有限的)。已确认仅当元素即将变得可见时才会触发“重新计算样式”(实际上这是有道理的)。