0 votes

Modifier dynamiquement les éléments du DOM au fur et à mesure qu'ils sont affichés (performance)

J'essaie de trouver un algorithme efficace pour charger dynamiquement les images d'arrière-plan d'un ensemble d'objets. <li> et ont des problèmes d'efficacité. Mon code actuel ressemble à ceci :

function elementInView($elem, vps, vpe) {
    var elempos = $elem.position(); 
    var pagestart = elempos.top + vps;
    var pageend = elempos.top + vps + $elem.height();
    var offset = 78 - Math.max(0,vps-pagestart) - Math.max(0,pageend-vpe);    
    // I want to update all items that are within 200 pixels of 
    // the current viewport
    return (vpe > 0 && offset > -200); 
}

$('#container').bind('scroll', function() {
    var $container = $(this);
    var vps = $container.scrollTop();
    var vpe = vps + $container.height();

    $('li:not(.bgset)', '#container').each(function() {
        var $this = $(this);
        if (elementInView($this,vps,vpe)) {
            $this.addClass('.bgset');
            // Set the background-image (doesn't affect performance noticably.)
        }
    });
});

Cette opération prend entre 200 et 600 ms pour une liste de ~250 éléments, et ~1500 ms pour une liste de ~1500 éléments, ce qui la rend pratiquement inutilisable.

Quelqu'un voit-il des problèmes ou est-ce la meilleure façon de procéder ? J'ai essayé d'obtenir TOUS les <li> au lieu de $('li:not(.bgset)' mais cela n'a pas vraiment eu d'impact.

(La liste contient des images d'arrière-plan générées dynamiquement (qui ne sont pas mises en cache ET qui sont modifiées assez souvent), et le chargement de ~1500 d'entre elles ralentissait vraiment tout, c'est pourquoi j'ai essayé cette approche).

EDIT : J'ai oublié de mentionner que j'ai pensé à écrire un sélecteur jQuery personnalisé qui correspond aux éléments qui retournent true pour elementInView Cette approche serait-elle préférable ?

1voto

AutomatedTester Points 14713

On dirait que votre application fait beaucoup de refontes et de repeints, ce qui nuit considérablement aux performances et à l'expérience des utilisateurs, sans parler de l'énorme quantité de trafic HTTP.

Avez-vous pensé à la possibilité de faire du spriting à la volée avec le CSS pertinent généré en même temps. De cette manière, vous pourriez espérer réduire les requêtes HTTP et le nombre de répétitions et de rejets.

1voto

Mic Points 13418

Le DOM est lent. Pour obtenir une vitesse brute, vous devez utiliser innerHTML.
Pour éviter les manipulations de chaînes de caractères, vous pouvez envisager un moteur de templating JS, il en existe de nombreux.
Nous avons construit le moteur de modélisation PURE En outre, comme il est minuscule et rapide, il fonctionne très bien pour construire des pages pour les mobiles.

Une autre option pourrait être de considérer le problème en amont. Êtes-vous sûr de vouloir fournir à votre utilisateur une liste de centaines/milliers d'éléments ?

1voto

Tout d'abord, je recommande l'utilisation d'un profileur pour obtenir une connaissance réelle de ce qui ralentit votre code. Il existe des profileurs dans firefox (firebug), chrome et explorer. Mais je peux penser à quelques problèmes pour l'instant.

Je suppose que tous les LI sont des enfants d'un même UL, et que vous pouvez donc y accéder directement ( firstChild / nextSibling ) sans appeler $() . Même s'il y a plus d'une UL, l'accès direct est toujours plus rapide que l'accès direct. $() .

Une autre raison possible est la complexité des CSS. J'ai vu un cas où, à cause d'un trop grand nombre de flottants et de positionnements unique l'accès à l'élément offsetTop a pris une demi-seconde. Cela pourrait influencer la vitesse de .height() y .position() .

Mais le profil d'abord !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X