Vous souvenez-vous encore qu'il existe une branche dans la fonction d'initialisation de jQuery jQuery.fn.init
//document ready简便写法$(function(){…}) } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } 所以$(fn)===$(document).ready(fn)。 来看一下jQuery.fn.ready的源码 ready: function( fn ) { // Add the callback jQuery.ready.promise().done( fn ); return this; }
Il est évident que le délai est défini dans la fonction jQuery.ready.promise et que la fonction fn est exécutée lorsque l'objet retard est résolu.
Flux de traitement principal :
Créez un objet retard et ajoutez l'événement de traitement une fois le document prêt à la liste des événements de réussite de l'objet retard.
jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); ... } return readyList.promise( obj ); }
Ajouter une fonction d'écoute pour l'état de préparation du document (fragment de fonction jQuery.ready.promise)
//标准浏览器支持DOMContentLoaded事件 } else if ( document.addEventListener ) { //绑定DOMContentLoaded事件和响应函数,响应函数会解决延时 document.addEventListener( "DOMContentLoaded", completed, false ); //回退到window.onload事件绑定,所有的浏览器都支持 window.addEventListener( "load", completed, false ); //如果是IE事件模型 } else { //确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全 document.attachEvent( "onreadystatechange", completed ); //回退到window.onload事件绑定,所有的浏览器都支持 window.attachEvent( "onload", completed ); //如果IE并且不是一个frame //不断地检查,看是否该文件已准备就绪 var top = false; try { top = window.frameElement == null && document.documentElement; } catch(e) {} if ( top && top.doScroll ) { (function doScrollCheck() { if ( !jQuery.isReady ) { try { // Use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ top.doScroll("left"); } catch(e) { return setTimeout( doScrollCheck, 50 ); } //移除之前绑定的事件 detach(); //执行延迟 jQuery.ready(); } })(); } }
Une fois qu'il est détecté que le document est prêt, appelez jQuery.ready pour exécuter la liste de rappel de réussite de l'objet retard : c'est-à-dire toutes les fonctions fn ajoutées via jQuery.ready(fn) [ou jQuery(fn)].
//ready事件处理函数 completed = function( event ) { // readyState === "complete"在老版本IE上适用 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { detach(); jQuery.ready(); } }, //清除ready事件绑定 detach = function() { if ( document.addEventListener ) { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); } else { document.detachEvent( "onreadystatechange", completed ); window.detachEvent( "onload", completed ); } }; //处理当DOM准备完成 jQuery.ready: function( wait ) { ... //设置DOM已经准备好的标志 jQuery.isReady = true; ... //执行绑定的延时事件 readyList.resolveWith( document, [ jQuery ] ); //触发任何绑定的就绪事件 if ( jQuery.fn.trigger ) { jQuery( document ).trigger("ready").off("ready"); } }
C’est tout le processus. Il y a quelques petits points de connaissances à régler.
a. Statut de chargement du document document.readyState
Document.readyState est utilisé pour déterminer l'état de chargement du document. Il s'agit d'un attribut en lecture seule. Les valeurs possibles sont :
. 0-non initialisé : l'objet XML est généré, mais aucun fichier n'est chargé.
1-loading : Le programme de chargement est en cours, mais l'analyse du fichier n'a pas encore commencé.
2-chargé : certains fichiers ont été chargés et analysés, mais le modèle objet n'a pas encore pris effet.
3-interactif : Valable uniquement pour une partie du fichier chargé. Dans ce cas, le modèle objet est valide mais en lecture seule.
4-complet : Le fichier a été complètement chargé, ce qui signifie que le chargement est réussi.
Exemple :
document.onreadystatechange = stateChange;//当页面加载状态改变的时候执行这个方法. function stateChange() { if(document.readyState == "complete"){ //当页面加载状态为完全结束时进入 alert("文档加载成功") } }
Cependant, l'ancienne version de Firefox ne prend pas en charge document.readyState [la dernière version de Firefox le prend déjà en charge]. Ainsi, si vous souhaitez être compatible avec tous les navigateurs, la préparation du document de suivi doit être réalisée dans deux situations :
- Les navigateurs standards utilisent addEventListener pour ajouter DOMContentLoaded et charger des écouteurs, et n'importe quel événement peut être déclenché
- L'ancienne version du navigateur IE utilise attachEvent pour ajouter onreadystatechange et onload à surveiller, n'importe lequel est déclenché et document.readyState === "complete" lorsque onreadystatechange.
C'est ainsi que jQuery le gère
jQuery.ready.promise = function(){ ... //标准浏览器支持DOMContentLoaded事件 else if ( document.addEventListener ) { //绑定DOMContentLoaded事件和响应函数,响应函数会解决延时 document.addEventListener( "DOMContentLoaded", completed, false ); //回退到window.onload事件绑定,所有的浏览器都支持 window.addEventListener( "load", completed, false ); //如果是IE事件模型 } else { //确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全 document.attachEvent( "onreadystatechange", completed ); //回退到window.onload事件绑定,所有的浏览器都支持 window.attachEvent( "onload", completed ); ... } } //ready事件处理函数 completed = function( event ) { // readyState === "complete"在老版本IE上适用 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { detach(); jQuery.ready(); } }
b.doScroll détecte que le chargement du document est terminé
C'est un moyen découvert par Diego Perini pour détecter si IE est chargé. Lien détaillé
Le principe est que lorsque la page DOM n'est pas chargée, une exception sera générée lors de l'appel de la méthode doScroll. Vous pourrez alors savoir si le document a été chargé en vérifiant en permanence si une exception se produit. Lorsqu'aucune exception ne se produit, le chargement du document est terminé.
(function doScrollCheck() { if ( !jQuery.isReady ) { try { // Use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ top.doScroll("left"); } catch(e) { return setTimeout( doScrollCheck, 50 ); } //移除之前绑定的事件 detach(); //执行延迟 jQuery.ready(); } })();