2009-07-01 5 views
2

J'ai une table html que je réorganise en fonction d'une liste CSV de valeurs d'attributs personnalisés que j'ai pour chaque ligne de table. J'utilise la fonction suivante pour le faire:L'appendTo de JQuery est très lent!

for (var i = 0; i < arrCSV.length; i++) 
{ 
    $('#' + tableId) 
     .find('[fname = ' + arrCSV[i] + ']') 
     .eq(0) 
     .parents('tr') 
     .eq(0) 
     .appendTo('#' + tableId); 
} 

La structure de la table est:

<table> 
<tr> 
<td fname='f1'>something here</td> 
</tr> 
<tr> 
<td fname='f2'>something here</td> 
</tr> 
</table> 

Le CSV pourrait être quelque chose comme ça "f2, f1"

Je trouve cela est très fonction d'exécution très lente. Toute aide pour l'optimiser est vraiment appréciée.

EDIT: Sur la base de l'article à http://www.learningjquery.com/2009/03/43439-reasons-to-use-append-correctly, on peut obtenir le plus grand coup de pouce de la performance en appelant append une seule fois par la chaîne concaténée html. Est-ce que quelqu'un peut aider à utiliser cette technique pour mon problème? Je ne suis pas sûr de savoir comment obtenir le code HTML dans la boucle for et l'ajouter une fois.

+0

Si vous voulez ajouter du HTML, vous devez vous assurer de supprimer les éléments précédents, sinon vous ne réorganisez pas la table, mais vous ajoutez simplement des éléments répétés à la fin. Vérifiez ma réponse ci-dessous (corrigée, mise à jour et testée) pour voir si elle améliore suffisamment vos performances pour coller avec appendTo qui va déplacer l'élément et éliminer le besoin de le supprimer explicitement. – tvanfosson

Répondre

1

Je suggère de trouver les éléments aussi peu de fois que possible. Stockez toutes les lignes correspondantes dans un "hachage" en utilisant la valeur d'attribut d'intérêt comme clé. Parcourez votre fichier CSV, sélectionnez la ligne correspondante dans le hachage, insérez-la dans un tableau, puis ajoutez les éléments du tableau à la table en utilisant l'objet jQuery précédemment trouvé.

var table = $('#' + tableId); 
var rowHash = {}; 
table.find('[fname]').each(function() { 
    rowHash[$(this).attr('fname')] = $(this).closest('tr'); 
}); 
var rows = []; 
for (var i = 0; i < arrCSV.length; ++i) 
{ 
    var row = rowHash[arrCSV[i]]; 
    if (row) { 
     rows.push(row); 
    } 
} 
$(rows).appendTo(table); 

EDIT: Cela semble être une légère amélioration à mon code précédent où je chaque ligne à AJOUT DE la table comme il a été trouvé. J'ai testé sur une table avec 1000 lignes et il semble prendre environ 1sec pour trier une table qui doit être complètement inversée.

+0

Je pourrais manquer quelque chose. Pouvez-vous me dire quelle ligne dans le code obtient le code HTML pour les TR? Merci pour l'aide! – Nick

+0

Ce n'est pas l'ajout via HTML. Il prend les éléments réels et les ajoute. La ligne $ (rows) .appendTo (table) prend chaque élément du tableau rows et l'ajoute à son tour à la table. Je pense que c'est assez rapide. Avec 50-100 (peut-être plus) lignes, il semble instantané. – tvanfosson

+0

Merci. J'ai été capable de l'abaisser de 67 à 43millisecondes en utilisant le code ci-dessus. Je souhaite qu'il y avait un moyen d'optimiser cela plus loin. – Nick

0

Vous devrez peut-être repenser votre algorithme.

Sans changer l'algorithme, une légère optimisation serait:

var $table = $("#" + tableId); 

for (var i = 0; i < arrCSV.length; i++) 
{ 
    $('[fname = ' + arrCSV[i] + ']:first',$table).closest('tr').appendTo($table); 
} 
0

Attendez une seconde ...

$('#' + tableId) 

Get #myTable

.find('[fname = ' + arrCSV[i] + ']') 

Trouver quoi que ce soit avec un attribut de fname égal à i

.eq(0) 

Donnez-moi le premier élément de l'expression précédente

.parents('tr') 

Trouvez des parents de type TR

.eq(0) 

Donne-moi la première dans l'expression précédente

.appendTo('#' + tableId); 

Ajouter que TR à #myTable

Okay. Maintenant que je l'ai décomposé - dupliquez-vous une ligne de table seulement? Si oui, le .append() n'est pas votre problème, votre choix de sélecteurs est. Pour aggraver ma confusion ici, les seules étiquettes avec un attribut de fname sont vos TR, alors pourquoi allez-vous à leurs parents() et à la recherche du premier TR? Vous demandez essentiellement que les balises TR soient placées dans les balises TR - mais ce n'est pas ce que montre votre exemple de balisage.

+0

Ahhh .. Désolé, Mon mauvais. L'attribut fname est sur le et non le – Nick

1

Si vous voulez ajouter html une seule fois (comme cet article de learningjquery.com), essayez ce qui suit:

$(document).ready(
function() 
{ 
    var arrCSV = ['f2', 'f1']; 
    var tableId = 'mainTable'; 
    var newTable = []; 
    for (var i = 0; i < arrCSV.length; i++) 
    { 
     var row = $('#' + tableId) 
       .find('[fname = ' + arrCSV[i] + ']') 
       .eq(0) 
       .parents('tr') 
       .eq(0); 

     newTable.push(row.html()); 
    }      

    $('#' + tableId).html(newTable.join('')); 
}; 
}); 

Live version: http://jsbin.com/uwipo code: http://jsbin.com/uwipo/edit

Bien que je pense personnellement que vous devriez profile ton code en premier et regarde si c'est append qui est lent OU cet appel de méthode 'find'. Je pense que pour une table énorme, l'utilisation de 'find method' pour trouver un attribut personnalisé pourrait être lente. Mais encore une fois, il ne sert à rien de faire des conjectures, de profiler le code et de le découvrir.

Si la méthode 'find' est lente, il sera possible d'utiliser l'attribut id sur td au lieu de donner un attribut personnalisé.

par exemple.

<table> 
<tr> 
    <td id='f1'>something here</td> 
</tr> 
<tr> 
    <td id='f2'>something here</td> 
</tr> 
</table> 

ensuite votre code pour trouver la ligne mère pourrait être aussi simple que:

('#' + arrCsv[i]).parent('tr') 

EDIT: Comme indiqué par tvanfosson, ce code suppose que arrCSV contient attribut pour toutes les lignes. La table finale contiendra uniquement les lignes présentes dans arrCSV. En outre, ce code ne copie pas la section 'thead', 'tfoot' de la table d'origine, bien qu'il soit facile d'écrire du code qui le fait.

+1

Cela suppose que chaque ligne de la table est triée par le fichier CSV ou que les lignes qui ne correspondent pas doivent être supprimées. C'est peut-être bien, mais vous devriez être conscient de cela. – tvanfosson

+0

Oui, vous avez raison. Je vais éditer mon post pour refléter cela. – SolutionYogi

+0

Puis-je réécrire sans utiliser la recherche et l'utilisation de l'attribut personnalisé? Malheureusement, je ne peux pas utiliser l'identifiant dans mon cas – Nick

Questions connexes