Question

J'ai une question concernant la vitesse de la page et l'optimisation du code.J'ai une page qui est peuplée à presque 100% par des appels AJAX.Ma question est la suivante: est-il plus rapide pour moi de coder plusieurs divs vides, de travées, peu importe dans le HTML de la page, puis de remplir ces éléments en utilisant javascript?Ou est-il plus rapide de créer ces éléments en javascript et de les insérer et de les ajouter? Je ne sais pas non plus s'il y a une grande différence.Ainsi, toute aide / conseil dans ce domaine serait grandement apprécié.

Était-ce utile?

La solution

Il y a quelques années, j'ai fait une expérience à ce sujet. Il est beaucoup plus rapide d'attribuer à la propriété innerHTML d'un élément pour créer une structure complexe que d'utiliser des appels répétés createElement appendChild insertBefore etc. J'ai déterré le message que j'ai fait à ce sujet (dans la liste de diffusion Prototype & script.aculo.us); ci-dessous.

N'oubliez pas qu'analyser le HTML et le rendre rapidement est ce que font les navigateurs , et ils sont hautement optimisés pour le faire. Si vous affectez une chaîne avec une structure HTML complexe à la propriété innerHTML d'un élément de conteneur, vous effectuez un voyage de la couche JavaScript à la couche de rendu du navigateur, après quoi l'analyse et le code de rendu du navigateur peut continuer sans interruption.

En revanche, si vous construisez cette structure complexe à l'aide de l'API DOM, non seulement il y a beaucoup de déplacements entre couches (JavaScript -> navigateur -> JavaScript), mais le navigateur doit également fonctionner avec l'API DOM plutôt que ses structures internes.

Par conséquent, il vaut généralement la peine de regarder un moteur de création de modèles JavaScript bien écrit (si vous voulez faire ce côté client). Ceux-ci "compileront" généralement le modèle une fois dans un formulaire facilement traité, et pendant le traitement d'un ensemble de données particulier, ils utiliseront des astuces comme construire la chaîne sous forme de fragments dans un tableau via Array#push, puis obtenir le résultat final via Array#join en passant "" comme séparateur. Pour les chaînes volumineuses, cela peut être plus rapide que la concaténation de chaînes, bien que le fait de savoir si elle est (et dans quelle mesure) dépend très de l'implémentation (Firefox's SpiderMonkey vs Chrome V8 vs JScript IE), contrairement au innerHTML vs . DOM, qui ne varie que dans la vitesse de sa vitesse.

Voici le message de la liste de diffusion d'il y a quelques années I parlait de (en gros ce que je dis ci-dessus; wow, c'était il y a deux ans), voici le Pastie il se réfère à, voici que copié dans JSBin , et enfin ... voici le code: (Notez que le code n'est pas destiné à être une chose de beauté et de joie pour toujours, c'était un hack rapide ... Pourtant, oui, j'aimerais penser que je piraterais quelque chose d'un peu mieux maintenant , deux ans plus tard.)

Cela peut valoir la peine de le convertir en quelque chose qui fonctionnera sur jsPerf . Pas le temps de faire ça maintenant, j'en ai peur.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style>
#log {
    border-bottom:  1px solid black;
}
#log p {
    margin:     0;
    padding:    0;
}
</style>
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/prototype/1/prototype.js'></script>
<script type='text/javascript'>
document.observe('dom:loaded', function() {
    $('btnDOMDirect').observe('click', useDOMDirect);
    $('btnPrototypeDOM').observe('click', usePrototypeDOM);
    $('btnHTML').observe('click', useHTML);

});

var numRows = 10;
var numCols = 10;

function usePrototypeDOM(evt)
{
    var table;
    var tbody;
    var tr;
    var td;
    var row;
    var col;
    var start;
    var end;

    start = (new Date()).getTime();

    table = new Element('table');
    tbody = new Element('tbody');
    table.appendChild(tbody);
    for (row = 0; row < numRows; ++row) {
        tr = new Element('tr');
        tbody.appendChild(tr);
        for (col = 0; col < numCols; ++col) {
            td = new Element('td');
            td.update('Row ' + row + ', col ' + col);
            tr.appendChild(td);
        }
    }
    $('targetTable').update(table);

    end = (new Date()).getTime();
    log('DOM took ' + (end - start) + 'ms');
}

function useDOMDirect(evt)
{
    var table;
    var tbody;
    var tr;
    var td;
    var row;
    var col;
    var start;
    var end;

    if (Prototype.Browser.IE) {
        alert("DOM direct doesn't work on IE because I used table elements.  Sorry.  The other two work.");
        return;
    }

    start = (new Date()).getTime();

    table = document.createElement('table');
    tbody = document.createElement('tbody');
    table.appendChild(tbody);
    for (row = 0; row < numRows; ++row) {
        tr = document.createElement('tr');
        tbody.appendChild(tr);
        for (col = 0; col < numCols; ++col) {
            td = document.createElement('td');
            td.update('Row ' + row + ', col ' + col);
            tr.appendChild(td);
        }
    }
    $('targetTable').update(table);

    end = (new Date()).getTime();
    log('DOM took ' + (end - start) + 'ms');
}

function useHTML(evt)
{
    var html;
    var row;
    var col;
    var start;
    var end;

    start = (new Date()).getTime();

    html = '<table><tbody>';
    for (row = 0; row < numRows; ++row) {
        html += '<tr>';
        for (col = 0; col < numCols; ++col) {
            html += '<td>Row ' + row + ', col ' + col + '</td>';
        }
        html += '</tr>';
    }
    html += '</tbody></table>';
    $('targetTable').update(html);

    end = (new Date()).getTime();
    log('HTML took ' + (end - start) + 'ms');
}

function log(msg)
{
    var l;
    var p;

    l = $('log');
    if (l) {
        p = new Element('p');
        p.update(msg);
        l.appendChild(p);
    }
}
</script>
</head>
<body>
<input type='button' id='btnDOMDirect' value='DOM Direct' />
<input type='button' id='btnPrototypeDOM' value='Prototype DOM' />
<input type='button' id='btnHTML' value='HTML' />
<div id='log'></div>
<div id='targetTable'></div>
</body>
</html>

Autres conseils

Il sera toujours plus lent d'utiliser javascript pour ce faire, car il s'exécute au-dessus du chargement de la page, plutôt qu'avec elle, comme le ferait l'ajout d'éléments au HTML.Cependant, vous pourriez aussi dire que la charge réelle de la page est moindre (mais pas de manière significative) sans avoir les éléments en HTML.

De plus, si vous êtes intéressé par la maintenance d'un site Web sémantique, avez-vous besoin de balises?Se dégrade-t-il gracieusement sans JavaScript?Etc etc. Cela dépend de l'angle que vous voulez prendre je suppose.

Si vous créez beaucoup d'éléments, innerHTML peut être beaucoup plus rapide, mais il ne fait pas partie du standard DOM officiel (bien qu'il soit largement pris en charge).Ma recommandation serait de servir la page avec une mise en page squelette, y compris autant de HTML que possible dans la page elle-même, puis de récupérer les références aux parties pertinentes de la page et de brancher les valeurs avec des méthodes DOM standard.

Cela devrait être raisonnablement rapide, gardera la présentation et la logique séparées, et finira probablement par être plus flexible dans le cas de futurs changements ou refontes du site.

Modifiez innerHTML au lieu d'utiliser les méthodes DOM.

D'après ce benchmark du W3C DOM vs innerHTML sur Quirksmode, il ressemble à toutles navigateurs testés sont beaucoup plus rapides en HTML qu’en DOM.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top