JQuery append в цикле - DOM не обновляется до конца

При переходе по большой коллекции и добавлении ее в DOM, DOM обновляется только после того, как все элементы были добавлены. Почему обновление DOM после каждого вызова append()? Могу ли я заставить DOM обновляться после каждого добавления (или, может быть, после каждого n числа добавлений)?

var i = 0;
for (i=0; i<5000; i++) {
    $('#collection').append('<li>Line Item</li>');
}

Ссылка на jsfiddle

ПРИМЕЧАНИЕ. Я понимаю, что более высокая производительность (исключая DOM reflow) может быть достигнута путем добавления всех элементов к локальной переменной, а затем добавления этой переменной в DOM. Но я хочу, чтобы первые n элементов отображались на экране, затем следующее n и т.д., Пока все элементы не будут отображаться.

Ответ 1

Большинство браузеров останавливается во время работы Javascript. Сюда относятся, например, рендеринг DOM, обработка событий, анимация изображения.

Единственный способ заставить DOM быть визуализированным - это закончить Javascript. Вы можете использовать метод setTimeout для запуска кода снова после обновления:

var  i = 0;

function appendSomeItems() {
  for (var j=0; j<50; i++, j++) {
    $('#collection').append('<li>Line Item</li>');
  }
  if (i < 5000) window.setTimeout(appendSomeItems, 0);
}

appendSomeItems();

Демо: http://jsfiddle.net/Uf4N6/

Ответ 2

вам нужно время от времени отдавать контроль браузеру:

    var current = 0


    function draw() {
        var next = current + 10
        for(var i = current; i < next; i++) {
            $('#collection').append('<li>Line Item</li>');
        }
        current = next
        setTimeout(draw, 50);
    }

draw();

Ответ 3

Как правило, пожалуйста, не нажимайте DOM слишком много раз. Это убийца производительности, как вы уже заметили.

var result="";
for (i=0; i<5000; i++) {
    result+='<li>Line Item</li>';
}
$('#collection').append(result);

Таким образом, вы коснетесь DOM только один раз!

Альтернативный способ - использовать массив.

var result=[];
for (i=0; i<5000; i++) {
    result.push('<li>Line Item</li>');
}
$('#collection').append(result.join(""));

Ответ 4

Если это действительно то, что вы хотите сделать...

var i = 0;
for (i=0; i<5000; i++) {
    setTimeout(function() {
        $('#collection').append('<li>Line Item</li>');
    }, 0);
}