我有一个来自服务器的大量集合,我需要为集合中的每一行创建DOM
个元素。
如果我尝试使用for循环将项目附加到DOM
,我的浏览器会挂起一段时间。为了避免这种情况,我尝试使用setTimeout
以块的形式添加项目,但是在处理完所有块之后,这些项目不会出现在UI中。
如果我在代码中添加了一个dubugger,对于每次迭代,我都会看到它出现在DOM
中。
我已经创建了一个样本来模拟这个。
var longArray = [];
for (var i = 0; i < 10000; i++) {
var item = {
"Name": "item" + i,
"Id": i
};
longArray.push(item);
}
var chunks = _.chunk(longArray, 2);
for (var i = 0; i < chunks.length; i++) {
(function(index) {
setTimeout(addItem(chunks[index]), 1000);
})(i);
}
function addItem(items) {
_.forEach(items, function(item) {
$("<li />").html(item.Id + " : " + item.Name).appendTo("ul");
});
}
&#13;
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
<ul></ul>
&#13;
对于demo,我添加了1秒的延迟,我期待在下一次执行该功能之前,先前添加的项目出现在屏幕上。
当前项目仅在处理完所有项目时出现在屏幕上。
答案 0 :(得分:2)
我不会详细说明,因为您将在此处获得许多相关主题。只是要理解你的代码中存在一个逻辑问题,基本上你的所有setTimeout都在1000ms后一起运行。例如,如下更改您的代码,它可以预期工作。
var longArray = [];
for (var i = 0; i < 10000; i++) {
var item = {
"Name": "item" + i,
"Id": i
};
longArray.push(item);
}
var chunks = _.chunk(longArray, 2);
function addItem() {
var items = chunks.pop();
_.forEach(items, function(item) {
$("<li />").html(item.Id + " : " + item.Name).appendTo("ul");
});
if (chunks.length) {
setTimeout(addItem, 1000);
}
}
addItem();
此外,您可以使用requestAnimationFrame
代替setTimeout,这将解决您的冻结问题,并且比setTimeout更好用