Performances de la méthode jQuery width ()

Je suis un noob jQuery qui essaie de résoudre un problème de performances que nous rencontrons avec les grandes tables. Nous avons un widget de table local qui, entre autres choses, définit la largeur des colonnes au maximum de la largeur de l’en-tête ou de la largeur des lignes.

Avec une table de 10 lignes par 500 colonnes, cela peut prendre presque 40 secondes (!), Ce qui semble excessif étant donné que la table peut être affichée en moins d’une seconde.

Voici la fonction entière:

var dataTable = this._div.find('.data-table'); var headerTable = this._div.find('.data-header-table'); if (dataTable.length === 0 || headerTable.length === 0) { return; } dataTable = dataTable[0]; headerTable = headerTable[0]; if (dataTable.rows.length === 0) { return; } var dataTr = dataTable.rows[0]; var headerTr = headerTable.rows[headerTable.rows.length - 1]; var marginColumnWidths = $(dataTr.cells[0]).outerWidth(true) + $(dataTr.cells[1]).outerWidth(true) + $(dataTr.cells[2]).outerWidth(true) - DOM.getHPaddings($(headerTr.cells[0])) + 1; $(headerTable) .find('> tbody > tr > td:first-child') .width('1%') .children() .first() .width(marginColumnWidths); for (var i = 1; i  div').width(commonWidth); dataTd.children().first().width(commonWidth); } 

Si je remplace

  var commonWidth = Math.max( Math.min(headerTd.width(), 100), dataTd.width() ); 

avec une constante

  var commonWidth = 100; 

le temps d’exécution passe de 38 secondes à moins d’une seconde, ce qui indique que le problème concerne la lecture / le calcul des largeurs actuelles, par opposition à la définition de la nouvelle largeur. D’après le profilage / l’échantillonnage que j’ai effectué, il semble que jQuery consacre une quantité de temps démesurée aux calculs CSS.

Quelqu’un peut-il recommander un moyen plus efficace de le faire?

MODIFIER:

J’ai essayé à la fois css (“width”) et outerWidth () sans modification significative des performances. Nous utilisions jQuery 1.7.2, mais la mise à niveau vers la version 1.8.1 n’a pas sensiblement modifié les performances.

Utilisez .css("width") au lieu de .width() , des modifications ont été apscopes à la méthode .width() qui ralentissent son exécution. Lisez ceci pour plus d’informations: http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-et-outerwidth/

 var commonWidth = Math.max( Math.min(parseFloat(headerTd.css("width")), 100), dataTd.width() ); 

Comme je le sais, – .width() prend la largeur réelle (pas toujours un ensemble dans css) et pour l’obtenir – le navigateur doit la calculer (mise à jour forcée et calcul de la largeur elle-même). Maintenant, vous définissez la largeur, le navigateur doit tout redessiner. Cela peut se faire avec un léger retard, mais à l’étape suivante, vous reprenez la largeur – le navigateur DOIT redessiner la page pour obtenir une largeur réelle. Commencez par compter les largeurs, puis, dans une autre boucle, définissez les valeurs calculées. Je pense que cela devrait aider

EDIT :

Testé cela en comparant à l’approche Kelvin B. La différence n’est pas significative. On dirait que le meilleur est lorsque css (“width”) est utilisé. Voici les tests: Hm. Testé cela. En comparant avec l’approche que j’ai suggérée. Apparu que la différence n’est pas grande. Voici les tests: largeur une boucle , css largeur une boucle , deux boucles css , largeur deux boucles . En résultat – presque pas de différence. Le plus lent – “largeur d’une boucle”. Le plus rapide – l’un de ceux avec css . Différent de temps en temps pour moi.

Remarque: quatre tests différents avec on case car js perf ne supprime pas l’état HTML entre les cas de test.

Je ne sais pas ce qui pourrait être fait dans votre cas, mais ce que je vois d’étrange, c’est .width('1%') vous utilisez. Pour moi, il semble que vous n’en ayez pas besoin, alors vous pouvez peut-être essayer de l’enlever.

Si vous faites .width (et aussi .css (“width”)) sur une cellule de tableau (ou des en-têtes) de très grands tableaux, cela prend énormément de temps POUR LES ÉLÉMENTS CACHÉS !!! La raison en est que si l’élément est masqué, le navigateur, étant agréable et efficace, n’a fait aucun effort pour savoir quelle serait la largeur, si l’élément était visible. Mais .width de jQuery, apparemment, pour les éléments cachés, retourne ce que serait la largeur, si elle était visible, au lieu de simplement renvoyer zéro (c’est bien caché). Pour les grandes tables, cela signifie que le navigateur doit restituer l’ensemble de la table. Si la table est vraiment grande, elle peut prendre une seconde. Et si vous le faites ensuite pour plusieurs colonnes masquées (il suffit de mesurer leur largeur), votre page devient inutile.

Donc, ne mesurez pas la largeur des éléments cachés sauf si vous devez VRAIMENT savoir.

lien pertinent, répétant ce que je viens de dire (et plus): ici