ホームページ > 記事 > ウェブフロントエンド > Jquery1.9.1 ソースコード解析シリーズ (6) 遅延オブジェクト応用 jQuery.ready_jquery
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; }
jQuery.ready.promise 関数に遅延が設定されており、遅延オブジェクトが解決されると fn 関数が実行されることがわかります。
主な処理フロー:
遅延オブジェクトを作成し、ドキュメントの準備ができた後の処理イベントを遅延オブジェクトの成功イベント リストに追加します。
jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); ... } return readyList.promise( obj ); }
ドキュメントの準備状況のリスニング関数を追加します (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(); } })(); } }
ドキュメントの準備ができていることが検出されたら、jQuery.ready を呼び出して、遅延オブジェクトの成功コールバック リストを実行します。つまり、jQuery.ready(fn) [または jQuery(fn)] を通じて追加されたすべての関数 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"); } }
これがプロセス全体です。整理すべき小さな知識ポイントがいくつかあります。
a. ドキュメントの読み込みステータス document.readyState
Document.readyState は、読み取り専用の属性です。
0-初期化されていない: XML オブジェクトは生成されますが、ファイルはロードされません。
1-loading: プログラムのロードは進行中ですが、ファイルの解析はまだ開始されていません。
2-loaded: 一部のファイルはロードおよび解析されましたが、オブジェクト モデルはまだ有効になっていません。
3-interactive: ロードされたファイルの一部に対してのみ有効です。この場合、オブジェクト モデルは有効ですが、読み取り専用です。
4-complete: ファイルは完全にロードされました。これは、ロードが成功したことを意味します。
例:
document.onreadystatechange = stateChange;//当页面加载状态改变的时候执行这个方法. function stateChange() { if(document.readyState == "complete"){ //当页面加载状态为完全结束时进入 alert("文档加载成功") } }
ただし、古いバージョンの Firefox は document.readyState をサポートしていません (最新の Firefox はすでにサポートしています)。したがって、すべてのブラウザと互換性を持たせたい場合は、次の 2 つの状況でモニタリング ドキュメントの準備を処理する必要があります。
- 標準ブラウザは addEventListener を使用して DOMContentLoaded を追加し、リスナーをロードし、任意のイベントをトリガーできます
- 古いバージョンの IE ブラウザは、attachEvent を使用して onreadystatechange と onload を監視に追加します。いずれかがトリガーされ、onreadystatechange の場合は document.readyState === "complete" になります。
これが jQuery の処理方法です
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 はドキュメントの読み込みが完了したことを検出します
これは、IE がロードされているかどうかを検出するために Diego Perini によって発見された方法です。詳細リンク
原則として、ページ DOM がロードされていない場合、 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(); } })();