L'événement DOMContentLoaded est-il exactement le même que la fonction.ready() de jQuery?

J'ai remplacé window.addEventListener('DOMContentLoaded', function() {}); par $(document).bind('ready', function() {}); de jQuery, car le premier n'a pas fonctionné sur IE .attachEvent() pour ce navigateur factice, si je pouvais avoir cela bien 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é autour de 0-2 milisecondes après le chargement / actualisation de la page (au moins c'est ce qui a été enregistré par mon script de journalisation), alors que .ready() nécessite toujours au moins 15-20 milisecondes, après actualisation de la page, pour être déclenché (encore - comme enregistré par script).

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

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

31
demandé sur trejder 2012-07-17 17:17:50

3 réponses

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

  1. L'événement réel peut supporter n'importe quel document. jQuery n'utiliser les document, il a été chargé, peu importe ce que vous lui transmettez.
  2. jQuery déclenchera l'événement de manière asynchrone même si l'événement s'est déjà produit. Attacher l'événement 'DOMContentLoaded' ne fera rien si l'événement s'est déjà produit.

Il N'y a pas de retard dans ces navigateurs, voir http://jsfiddle.net/rqTAX/3/ (les décalages enregistrés sont milliseconde).

Pour les navigateurs qui ne supportent pas l'événement, jQuery fonctionnera évidemment pour eux aussi. Il utilisera un mécanisme hacky qui n'est pas le même que le réel DOMContentLoaded et ne se déclenchera pas nécessairement dès que le réel DOMContentLoaded le ferait:

// 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();
}
19
répondu Esailija 2012-07-17 14:16:22

JQuery simule cet événement en se liant à l'événement readystatechange de document, qui est la manière 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 déclenche après cela; peut-être qu'il attend le rendu de la 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 les document de readyState à " terminer."

(Si quelqu'un a une réponse définitive, postez un commentaire et je mettrai à jour cette réponse; j'aimerais savoir exactement quand il se déclenche, et je ne trouve pas cette réponse dans aucune documentation ou sur tous les sites auxquels je m'attends comme Quirksmode.)

4
répondu ajm 2012-07-17 13:46:43

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 à celui-ci. Si l'un d'entre eux sont des opérations synchrones de longue durée, l'événement ready viendra beaucoup plus tard. Par exemple, j'utilise knockout.js et il peut prendre 500ms pour initialiser la page.


Cependant, en utilisant votre page de test minimale, ce 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 6ms même pour votre simple super page


Aussi, j'ai pris votre code et l'ai couru à travers les outils de performance de Chrome et j'ai découvert quelques choses intéressantes:

entrez la description de l'image ici

  • BTW: la barre bleue verticale est DOMCONTENTLOADED et le vert est 'first paint'
  • Vous pouvez voir même un appel de fonction super simple sur L'événement DOMCONTENTLOADED peut prendre 5ms (et c'est sur un i7). Rappelez-vous qu'il doit être analysé et que les choses doivent être initialisées.
  • Les rappels sont affichés dans le cyan couleur (anonyme), le premier provient de L'événement DOMCONTENTLOADED et le second est le rappel 'ready'.
  • Vous remarquerez 'Minuterie Flamme" (c'est à dire setTimeout). Donc, ce n'est pas instantané par tous les moyens.

En regardant le code source jQuery , Vous voyez qu'ils définissent réellement une minuterie 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 veulent dire 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 bloquer l'interface utilisateur mais "retarder prêt" n'est pas clair pour moi.

1
répondu Simon_Weaver 2017-02-22 00:54:00