Клиентский JavaScript, создание нескольких элементов и показ каждого в кратчайшие сроки.
-
18-09-2019 - |
Вопрос
Код JavaScript на стороне клиента создает несколько элементов (около 50-100) за цикл:
for (var i = 0; i < list.length; i++) {
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
mainObj.appendChild(obj);
}
Есть некоторые проблемы с рендерингом браузера.Например, IE просто зависает, пока не завершит цикл, а затем показывает все элементы сразу.Есть ли способ показать каждый созданный элемент отдельно и сразу после appendChild()
?
Решение
вставьте задержку между добавлением последовательных записей, с помощью setTimeout()
.
function insertEntry(list, ix) {
if (ix == null) {
ix = 0;
}
else if (ix < list.length) {
var elt= document.createElement("DIV");
var attr = document.createAttribute('id');
attr.value = 'item'+ix;
elt.setAttributeNode(attr);
elt.innerHTML = "<span class='itemCls'>" + list[ix].Id + ': ' + list[ix].Name +
"</span><!-- some more simple code -->\n";
mainObj.appendChild(elt);
ix++;
}
if (ix < list.length) {
setTimeout(function(){insertEntry(list, ix);}, 20);
}
}
Начните с:
insertEntry(myList);
где myList выглядит так:
var myList = [
{ Id : '1938377', Name : 'Sven'},
{ Id : '1398737', Name : 'Walt'},
{ Id : '9137387', Name : 'Edie'}
...
};
демо: http://jsbin.com/ehogo/4
Другие советы
Это связано с однопоточной природой браузеров.Рендеринг не начнется, пока поток не станет бездействующим.В данном случае это происходит после завершения цикла и выхода из функции.Единственный способ обойти эту проблему — (своего рода) смоделировать несколько потоков с помощью таймеров, например:
var timer,
i = 0,
max = list.length;
timer = window.setInterval(function ()
{
if (i < max)
{
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
mainObj.appendChild(obj);
i++;
}
else
window.clearInterval(timer);
}, 1);
Очевидным недостатком является то, что для завершения этого цикла потребуется больше времени, поскольку он соответствует рендерингу между каждой итерацией.
Я бы сделал это вот так, используя jQuery вместо:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(document).ready(function() {
timer = window.setInterval(function ()
{
for (var i = 0; i < 100; i++) {
$('#container').append('<div>testing</div><br />');
}
},10);
});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
jQuery делает это так быстро, что вам даже не придется беспокоиться об отображении процесса создания, но вы можете сделать это более плавно, добавив таймер, как показано в примере.
Есть ли конкретная причина, по которой вы хотите, чтобы DOM обновлялся после каждого цикла?Было бы намного быстрее, если бы вы создали все элементы в одном элементе javascript и добавили этот элемент в DOM после завершения цикла.
var holder = document.createElement("DIV");
for (var i = 0; i < list.Length; i++) {
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
holder.appendChild(obj);
}
mainObj.appendChild(holder);