2011-03-03 43 views
5

Estoy usando un plugin jquery que corrige los encabezados en una tabla html que genero. Por desgracia, el rendimiento del plugin es muy lento y yo he reducido al siguiente código:¿Por qué este jquery es tan lento?

var $tbl = $(this); 
var $tblhfixed = $tbl.find("thead"); 
$tblhfixed.find("th").each(function()  
    $(this).css("width", $(this).width()); 
}); 

Esto es tomar unos 40 segundos sobre una mesa con 2.000 filas en el IE. ¿Alguien sabe por qué es tan lento y más importante cómo puedo hacerlo más rápido? He probado muchos otros complementos y este es el único que funciona como yo quiero. Gracias por cualquier ayuda

+0

¿el t la cantidad de filas hace la diferencia (¿Has probado esto)? Solo manipulas el encabezado de la tabla. ¿Cuántas columnas hay? Debe usar un filtro en lugar de un hallazgo. http://groups.google.com/group/jquery-en/browse_thread/thread/533451087251c952/9bb31c108c089c4f y http://www.learningjquery.com/2006/12/how-to-get-anything-you-want- part-2 –

+1

¿Qué es 'esto'? ¿Cuál es el contexto? Un http://jsfiddle.net sería genial :) –

+0

Disculpe, 'esto' es una referencia a la tabla donde estoy aplicando el complemento – nzyme

Respuesta

1

el culpable es probablemente el .each.

La razón es que cuando itera usando .each en lugar de un bucle normal, llama a una función para cada iteración. En este caso, una llamada a una función tiene una sobrecarga bastante grande, ya que debe crearse una nueva pila de llamadas para cada iteración.

para hacerlo más rápido cambiar

$tblhfixed.find("th").each(function()  
    $(this).css("width", $(this).width()); 
}); 

a

var elms = $tblhfixed.find("th"); 
for(var i=0, elm;elm = elms[i];i++) { 
    elm.css("width", elm.width()); 
} 
+0

aunque es cierto, creo que la tara '.each()' es insignificante, en comparación con las llamadas repetidas a '$ (this)' – Chii

+2

En realidad, la sobrecarga de cada uno es bastante masiva, intente ver aquí: http: // jsperf. com/jquery-each-vs-for-loop/6 –

+0

'width()' tampoco es la función más rápida del universo, IIRC, así que también almacenaría esa llamada en caché. –

1

no se debe repetir $(this) dentro de su función pasó a .each(). envolver un elemento tiene una sobrecarga no trivial, lo cual no está bien cuando tienes 20k elementos. desea eliminar tanto trabajo como sea posible dentro de la llamada .each(), o eliminarlo por completo.

Además, ¿por consulta find() dos veces, cuando se puede hacer esto en su lugar, que debe dar los mismos resultados:

$ths = $('table thead th'); //or tableid, or something 
$ths.css('width', $ths.width()); 
+0

¿Por qué establece el ancho 'th' en el ancho' table'? Esto no es lo que está haciendo el código OP. –

+0

ah leí mal el código - debería sacar las llamadas parent() – Chii

0

En primer lugar, se debe utilizar find() sólo cuando se necesita pasar a través de todos los nodos anidados. Aquí puede usar children().

En segundo lugar, cada vez $(this) crea nueva instancia de objeto jQuery, mientras que se puede crear una vez:

var $this = $(this); 

Cada vez $(this).width() se recalcula. Asegúrese de que necesita que se vuelva a calcular. O DO:

var tableWidth = $this.width(); 

Y en tercer lugar, de acuerdo a @ Martin Jespersen, cada iteración se crea el objeto function.

Además, no necesita jQuery aquí en absoluto. Puede acceder al DOM directamente:

var tableWidth = ...; // get the table width the way you want 
var thead = this.tHead; 
var thRow = thead.rows[0]; 
for (var i = 0; i < thRow.length; ++i) { 
    thRow.cells[i].style.width = tableWidth + "px"; 
} 
1

Creo que se enfrentó con el mismo problema que tuve hace un tiempo. Se llamaba "Recalcular diseño" o algo así.

tratar de separar este script en dos bucles, así:

var $tbl = $(this); 
var $tblhfixed = $tbl.find("thead"); 
var widths = []; 

// 1. 
$tblhfixed.find("th").each(function() 
    widths.push($(this).width()); 
}); 

// 2. 
$tblhfixed.find("th").each(function (index, element) 
    $(this).css("width", widths[index]); 
}); 

El primero calculará todos los anchos.Segundo, se aplicará a TH

UPD: Usted puede aumentar el rendimiento mediante la colocación de este código entre 1 y 2 .:

$tblhfixed.hide(); 

y mostrar de nuevo después de 2 .:

$tblhfixed.show(); 
+0

Eso realmente me ayudó, aunque no entiendo completamente por qué y realmente mi código aún funciona bastante lento, definitivamente más rápido que antes, pero aún lento. – Graf

Cuestiones relacionadas