2013-09-27 8 views
10

Quando si esegue il ciclo su una grande raccolta e la si aggiunge al DOM, il DOM si aggiorna solo dopo che tutti gli elementi sono stati aggiunti. Perché il DOM non si aggiorna dopo ogni chiamata append()? Posso forzare il DOM ad aggiornare dopo ogni append (o forse dopo ogni n numero di appends)?jQuery append in loop - DOM non si aggiorna fino alla fine

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

Link to jsfiddle

NOTA: So che prestazioni migliori (evitando DOM reflow) può essere ottenuto aggiungendo tutti gli elementi di una variabile locale e quindi aggiungendo quella variabile al DOM. Ma voglio che i primi n elementi vengano visualizzati sullo schermo, quindi i successivi n, ecc. Fino a quando tutti gli elementi non sono renderizzati.

+0

Penso che lo faccia, ma penso che blocchi l'interfaccia utente mentre fa il grande ciclo, quindi sembra che abbia fatto tutto in una volta ma non è così. –

risposta

10

La maggior parte tutto nelle fermate del browser mentre un Javascript è in esecuzione. Questo include ad esempio il rendering DOM, la gestione degli eventi, l'animazione delle immagini.

L'unico modo per eseguire il rendering del DOM consiste nel terminare Javascript. È possibile utilizzare il metodo setTimeout per avviare il codice di nuovo dopo l'aggiornamento:

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(); 

Demo: http://jsfiddle.net/Uf4N6/

+0

Grande spiegazione ed esempio, grazie! – Domenic

-3

Se questo è davvero quello che vuoi fare ...

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

è necessario restituire il controllo al browser ogni tanto un po ':

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(); 
-2

In generale, si prega di non toccare DOM troppe volte. È un killer delle prestazioni, come hai già osservato.

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

In questo modo, si tocca DOM solo una volta!

Un modo alternativo è utilizzare la matrice.

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

NOTA: Comprendo che è possibile ottenere prestazioni migliori (evitando il reflow DOM) aggiungendo tutti gli elementi a una variabile locale e quindi aggiungendo tale variabile al DOM. Ma voglio che i primi n elementi vengano visualizzati sullo schermo, quindi i successivi n, ecc. Fino a quando tutti gli elementi non sono renderizzati. – Domenic

+0

O sì. Scusa se non ho risposto al tuo bisogno. – Blaise

Problemi correlati