web-dev-qa-db-fra.com

L'événement DOMContentLoaded est-il EXACTEMENT identique à la fonction .ready () de jQuery?

J'ai remplacé window.addEventListener('DOMContentLoaded', function() {}); par jQuery's $(document).bind('ready', function() {});, car le premier n'a pas fonctionné sur IE <9 et je ne voulais pas jouer avec .attachEvent() pour ce navigateur factice, si je pouvais avoir cela joliment couvert par jQuery lui-même.

Peu de temps après le remplacement, j'ai remarqué que l'événement DOMContentLoaded était toujours déclenché environ 0 à 2 millisecondes après le chargement/rafraîchissement de la page (du moins c'est ce qui était consigné par mon script de journalisation), tandis que .ready() toujours nécessite au moins 15-20 millisecondes, après l'actualisation de la page, pour être déclenché (à nouveau - comme enregistré par le script).

Je demande uniquement à nourrir ma curiosité, pourquoi il y a un retard aussi "important"? Bien sûr, il n'y a pas de problème pour moi, que jQuery déclenche cet événement plus tard. C'est juste que parce que je veux connaître TOUTES les réponses (et gouverner le monde!:]), Je ne peux pas dormir avec ça! :]

[~ # ~] éditez [~ # ~] : dans . ready () fonction doc un utilisateur (Nick (de Nexxar)) souligne que: " jQuery simule l'événement" DOMContentLoaded "non existant sur IE, mais le mécanisme utilisé se déclenche beaucoup plus tard que l'événement utilisé sur d'autres navigateurs". Peut-être que c'est la même chose, je demande?

34
trejder

En supposant que le navigateur prend en charge l'événement:

  1. L'événement réel peut prendre en charge n'importe quel document. jQuery n'utilisera que le document dans lequel il a été chargé, peu importe ce que vous lui passez.
  2. jQuery déclenchera l'événement de manière asynchrone même si l'événement s'est déjà produit. Joindre 'DOMContentLoaded' événement ne fera rien si l'événement s'est déjà produit.

Il n'y a aucun retard dans ces navigateurs, voir http://jsfiddle.net/rqTAX/3/ (les décalages enregistrés sont en millisecondes).

Pour les navigateurs qui ne prennent pas en charge l'événement, jQuery fonctionnera évidemment pour eux également. Il utilisera un mécanisme hacky qui n'est pas le même que le vrai DOMContentLoaded et ne se déclenchera pas nécessairement dès que le vrai DOMContentLoaded:

// The DOM ready check for Internet Explorer
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }

    try {
        // If IE is used, use the trick by Diego Perini
        // http://javascript.nwbox.com/IEContentLoaded/
        document.documentElement.doScroll("left");
    } catch(e) {
        setTimeout( doScrollCheck, 1 );
        return;
    }

    // and execute any waiting functions
    jQuery.ready();
}
22
Esailija

jQuery simule cet événement en se liant à l'événement document de readystatechange, qui est le moyen standard de simuler DOMContentLoaded dans oldIE.

Selon la source jQuery , cet événement se déclenche "tard" mais avant window.onload. Cependant, je ne trouve pas quand cet événement se déclenche exactement. DOMContentLoaded se déclenche lorsque le DOM est construit et prêt pour les scripts, donc readystatechange se déclenche après cela; peut-être attend-il le rendu de mise en page ou le style de quelque chose comme ça, ou l'événement est déclenché plus tard dans le processus de rendu/mise en page?

Quoi qu'il en soit, il se déclenchera probablement après DOMContentLoaded, probablement en raison du moment où IE décide de mettre à jour le documentreadyState pour "terminer".

(Si quelqu'un a une réponse définitive, postez un commentaire et je mettrai à jour cette réponse; j'aimerais savoir quand exactement il se déclenche moi-même, et je ne trouve cette réponse dans aucune documentation ou sur aucun site auquel je m'attendrais comme Mode de quirks.)

4
ajm

Une autre raison pour laquelle le "prêt" semble se déclencher plus tard (en pratique) est qu'il peut y avoir de nombreux événements liés à lui. Si l'une de ces opérations est synchrone de longue durée, l'événement prêt interviendra beaucoup plus tard. Par exemple, j'utilise knockout.js et cela peut prendre 500 ms pour initialiser la page.


Cependant, utiliser votre page de test minimale n'est pas le cas, bien sûr. J'ai essayé d'exécuter ce qui suit:

 console.log(window.performance.timing.domContentLoadedEventEnd -
             window.performance.timing.domContentLoadedEventStart);

Cela donne environ 6 ms même pour votre super page simple


J'ai également pris votre code et l'ai exécuté à travers les outils de performance de Chrome et découvert quelques choses intéressantes:

enter image description here

  • BTW: la barre bleue verticale est DOMCONTENTLOADED et le vert est 'first Paint'
  • Vous pouvez voir même juste un appel de fonction super simple sur l'événement DOMCONTENTLOADED peut prendre 5 ms (et c'est sur un i7). N'oubliez pas qu'il doit être analysé et que les choses doivent être initialisées.
  • Les rappels sont affichés en couleur cyan (anonyme), le premier provient de l'événement DOMCONTENTLOADED et le second est le rappel "prêt".
  • Vous remarquerez 'Timer Fired' (c'est-à-dire setTimeout). Ce n'est donc pas instantané du tout.

En regardant le code source jQuery vous voyez qu'ils ont réellement mis un temporisateur pour les rappels:

// Handle it asynchronously to allow scripts the opportunity to delay ready
window.setTimeout( jQuery.ready );

Je ne suis pas exactement sûr de ce qu'ils signifient ici (n'importe quelle idée) - mais cela explique le comportement. Je pouvais voir qu'il était utile d'éviter les conditions de course et de bloquer l'interface utilisateur, mais "retarder prêt" n'est pas clair pour moi.

1
Simon_Weaver

Est-ce que quelqu'un utilise encore jQuery sauf moi? ;)

Depuis jQuery 3.0 , seule la syntaxe $( handler ) est recommandée,
(ce qui équivaut à $( document ).ready( handler )).

Depuis les documents de l'API: . Ready ()

0
SergO