2008-09-19 15 views
21

A continuación se muestra el código que utilizo para construir una tabla HTML sobre la marcha (usando datos JSON recibidos del servidor).Creando una tabla HTML sobre la marcha usando jQuery

Muestro un gráfico animado de pleasewait (.gif) mientras se cargan los datos. Sin embargo, el gráfico se congela mientras que la función de JavaScript está construyendo la tabla. Al principio, estaba feliz de hacer que esto sucediera (mostrar la tabla), creo que ahora necesito trabajar en la eficiencia. Por lo menos, necesito evitar que el gráfico animado se congele. Puedo ir a una pantalla estática de "carga", pero prefiero que este método funcione.

Sugerencias para mi pantalla de espera de por vida? Y la eficiencia? ¿Posiblemente una mejor forma de construir la mesa? O tal vez no una mesa, sino algún otro "mesa" como pantalla

var t = eval("(" + request + ")") ; 
var myTable = '' ; 
myTable += '<table id="myTable" cellspacing=0 cellpadding=2 border=1>' ; 
myTable += "<thead>" ; 
myTable += "<tr>"; 
for (var i = 0; i < t.hdrs.length; i++) { 
    myTable += "<th>"  + header +  "</th>"; 
} 
myTable += "</tr>" ; 
myTable += "</thead>" ; 
myTable += "<tbody>" ; 

for (var i = 0; i < t.data.length; i++) { 
    myTable += '<tr>'; 
    for (var j = 0; j < t.hdrs.length; j++) { 
     myTable += '<td>'; 
     if (t.data[i][t.hdrs[j]] == "") { 
      myTable += "&nbsp;" ; 
     } 
     else { 
      myTable += t.data[i][t.hdrs[j]] ; 
     } 
     myTable += "</td>"; 
    } 
    myTable += "</tr>"; 
} 
myTable += "</tbody>" ; 
myTable += "</table>" ; 

$("#result").append(myTable) ; 
$("#PleaseWaitGraphic").addClass("hide"); 
$(".rslt").removeClass("hide") ; 
+0

¿Aproximadamente cuántas columnas y filas está creando en este código? –

Respuesta

26

Básicamente, desea configurar sus bucles para que cedan a otros hilos cada cierto tiempo.Aquí hay un código de ejemplo this article sobre el tema de las operaciones intensivas de la CPU en funcionamiento sin provocar la congelación de la interfaz de usuario:

function doSomething (progressFn [, additional arguments]) { 
    // Initialize a few things here... 
    (function() { 
     // Do a little bit of work here... 
     if (continuation condition) { 
      // Inform the application of the progress 
      progressFn(value, total); 
      // Process next chunk 
      setTimeout(arguments.callee, 0); 
     } 
    })(); 
} 

En cuanto a la simplificación de la producción de HTML en su script, si estás usando jQuery, es posible que dé mi Simple Templates plug-in, prueba. Arregla el proceso reduciendo drásticamente la cantidad de concatenaciones que tienes que hacer. Funciona bastante bien, también después de que recientemente realicé algunas refactorizaciones que resultaron en un gran speed increase. He aquí un ejemplo (sin hacer todo del trabajo por usted!):

var t = eval('(' + request + ')') ; 
var templates = { 
    tr : '<tr>#{row}</tr>', 
    th : '<th>#{header}</th>', 
    td : '<td>#{cell}</td>' 
}; 
var table = '<table><thead><tr>'; 
$.each(t.hdrs, function (key, val) { 
    table += $.tmpl(templates.th, {header: val}); 
}); 
... 
+0

Gracias, aprecio el plugin de Plantillas simples. FYI, su aplicación de enlace de aumento de velocidad está rota. Obtengo un puñado de errores de JavaScript cuando intento ejecutar cualquier prueba. – Rich

+0

Gracias por avisarme, Rich. El problema era que las pruebas asumían una versión anterior de jQuery. La versión más nueva incluida en el pie de página rompió la forma en que había escrito los complementos. Ahora está arreglado, si quieres volver a intentarlo. –

+0

Su sitio está caído. ¿Le importaría proporcionar un ejemplo completo? –

3

Lo que está haciendo es construir una cadena, y luego analizar todo de una vez después de la inserción. ¿Qué ocurre con la creación de un elemento de tabla real (es decir, $("<table>")) y, a continuación, agregarle cada fila? Para el momento en que realmente lo insertes en la página, todos los nodos DOM se habrán construido, por lo que no debería ser tan grande.

0

Para empezar, echa un vistazo a flydom y sus variantes, ayudarán enormemente. ¿Podrías dar más contexto? Si esto no está en la carga y solo se pega en la página, simplemente envolver todo en $ (función() {/ * código * /}) probablemente borrará todo lo que tenga problemas. Inline JS se ejecuta inmediatamente, lo que significa que el bucle para la tabla. onload es un evento y esencialmente 'separado'.

-2

Puede insertar la tabla en el DOM bit por bit. Honestamente, no estoy del todo seguro de que esto ayude con tu problema, pero vale la pena intentarlo. Yo lo haría más o menos así (código no probado, se podría afinar un poco más):

$("#result").append('<table id="myTable" cellspacing=0 cellpadding=2 border=1></table>'); 
$('#myTable').append('<thead><tr></tr></thead>'); 
$('#myTable').append('<tbody></tbody>'); 

for (var i = 0; i < t.hdrs.length; i++) { 
    $('#myTable thead tr').append('<th>'+header+'</th>'); 
} 

for (var i = 0; i < t.data.length; i++) { 
myTr = '<tr>'; 
for (var j = 0; j < t.hdrs.length; j++) { 
    myTr += '<td>'; 
    if (t.data[i][t.hdrs[j]] == "") { 
    myTr += "&nbsp;" ; 
    } 
    else { 
    myTr += t.data[i][t.hdrs[j]] ; 
    } 
    myTr += "</td>"; 
    } 
myTr += "</tr>"; 
$('#myTable tbody').append(myTr); 
} 

$("#PleaseWaitGraphic").addClass("hide"); 
$(".rslt").removeClass("hide") ; 
0

Mi experiencia ha sido que hay dos retrasos discretos. Uno está concatenando todas esas cuerdas. La otra es cuando el navegador realmente intenta renderizar la cadena. Normalmente, IE es el que tiene más problemas con la IU se congela, en parte porque es mucho más lento al ejecutar JavaScript. Esto debería mejorar en IE8.

Lo que sugeriría en su caso es dividir la operación en pasos. Digamos que para una tabla de 100 filas, primero se genera una tabla válida de 10 filas. A continuación, lo envías a la pantalla y utilizas un setTimeout para devolver el control al navegador para que la UI deje de bloquear. Cuando el setTimeout vuelve, usted hace las siguientes 10 filas, etc.

La creación de la tabla con DOM es ciertamente "más limpia", como han dicho otros. Sin embargo, hay un alto precio para pagar en términos de rendimiento. Consulte el excelente artículo quirksmode sobre este tema, que tiene algunos puntos de referencia que puede ejecutar usted mismo.

Larga historia corta, innerHTML es mucho, mucho más rápido que DOM, incluso en motores JS modernos.

+0

Nadie ha sugerido crear la tabla usando el DOM, por lo que su referencia no es aplicable. Insertar contenido con innerHTML crea nodos DOM. Referirse a este hecho no es lo mismo que sugerir el uso de createElement. – Jim

11

He estado usando JTemplates para lograr lo que está describiendo. Dave Ward tiene un ejemplo en su blog here. El principal beneficio de JTemplates es que su html no está entrelazado en su javascript. Usted escribe una plantilla y llama a dos funciones para que jTemplate cree el html a partir de su plantilla y su json.

+1

Definitivamente estoy de acuerdo, la creación de plantillas del sitio del cliente es la mejor forma de crear elementos HTML a partir de una fuente de datos. –

3

Uso innerHtml definitivamente puede ser mucho más rápido que el uso de HTML-a-DOM-ifier de jQuery, que utiliza innerHTML pero hace un montón de procesamiento en las entradas.

Sugiero revisar chain.js como una forma de construir rápidamente tablas y otras estructuras de datos repetidos desde objetos de JavaScript. Es un complemento de enlace de datos inteligente y ligero para jQuery.

0

Busque en la web JavaScript y StringBuilder. Una vez que tenga un generador de cadenas JavaScript, asegúrese de utilizar el método .append para cada concatenación. Es decir, no desea tener ninguna concatenación de +. Después de eso, busque JavaScript y replacehtml. Use esta función en lugar de innerHTML.

Cuestiones relacionadas