この記事では、jQuery の Ready 関数がどのように機能するかを詳細に分析します。参考のために皆さんと共有してください。詳細は次のとおりです:
jQuery は優れたスクリプト ライブラリであり、最初のバージョンは 2006 年 1 月に BarCamp NYC で John Resig によってリリースされました。最新バージョンは http://jquery.com/ からダウンロードできます。この記事の公開時点では、jQuery バージョン 2.1.4 に更新されています。ここでは jQuery1.8.3 を例に挙げます。
jQuery を学習するにはさまざまな方法があります。今日は jQuery の Ready 関数から始めます。この例のコードは、jQuery スクリプト ライブラリからのものです。
jQuery を使用したことがある場合は、ready 関数を使用したことがあるはずです。この関数は、ページの準備ができたときに実行できる関数を登録するために使用されます。
問題は、私たちのページがいつ完成するかということです。
1. オンロードイベント
最も基本的な処理方法は、ページの onload イベントです。このイベントを処理する場合、HTML を通じて body 要素の開始タグに直接記述する方法や、イベント登録に使用するメソッドは、DOM0 メソッドと DOM2 メソッドに分けられます。ブラウザの互換性を考慮して、以下のようにDOM2モードで記述します。
if (document.addEventListener) { // A fallback to window.onload, that will always work window.addEventListener("load", jQuery.ready, false); // If IE event model is used } else { // A fallback to window.onload, that will always work window.attachEvent("onload", jQuery.ready); }
2. DOMContentLoaded イベント
ただし、onload イベントは、ページ上の画像などを含むすべてのページ要素が読み込まれるまでトリガーされません。 Web ページに多数の写真がある場合、ユーザーが写真を見る前にページの操作を開始した可能性が考えられます。この時点では、ページは初期化されておらず、イベントも登録されていません。 . それは遅すぎますよね?
DOM の onload イベントに似たよく知られた onload イベントに加えて、標準ベースのブラウザではこのイベントがサポートされており、このイベントはすべての DOM が解析されるときにトリガーされます。 。
このようにして、標準ベースのブラウザの場合、このイベントの処理を登録することもできます。このようにして、読み込み完了イベントをより早くキャッチできるようになります。
if (document.addEventListener) { // Use the handy event callback document.addEventListener("DOMContentLoaded", DOMContentLoaded, false); // A fallback to window.onload, that will always work window.addEventListener("load", jQuery.ready, false); }
3.onreadystatechange イベント
標準以外のブラウザではどうすればよいですか?
ブラウザに document.onreadystatechange イベントがある場合、イベントがトリガーされて document.readyState=complete になると、DOM ツリーがロードされたと見なされます。
ただし、このイベントはあまり信頼性がありません。たとえば、ページに画像がある場合、onload イベントが終了するまでトリガーされない可能性があります。つまり、ページにバイナリが含まれていない場合にのみ正しく実行されます。リソースが非常に少ないか、代替としてキャッシュされます。
if (document.addEventListener) { // Use the handy event callback document.addEventListener("DOMContentLoaded", DOMContentLoaded, false); // A fallback to window.onload, that will always work window.addEventListener("load", jQuery.ready, false); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent("onreadystatechange", DOMContentLoaded); // A fallback to window.onload, that will always work window.attachEvent("onload", jQuery.ready); }
DOMContentLoaded 関数は何をしているのですか?最後に、jQuery.ready 関数を呼び出す必要があります。
DOMContentLoaded = function() { if ( document.addEventListener ) { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); } else if ( document.readyState === "complete" ) { // we're here because readyState === "complete" in oldIE // which is good enough for us to call the dom ready! document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }
4. doScroll 検出メソッド
MSDN には、JScript メソッドに関する目立たない記述があります。ページ DOM がロードされていない場合、doScroll メソッドが呼び出されるときに例外が生成されます。次に、それを逆に使用します。例外がなければ、ページ DOM はロードされています。
Diego Perini は 2007 年に、doScroll メソッド呼び出しを使用して、IE がロードされているかどうかを検出する方法を報告しました。詳細な手順については、こちらをご覧ください。
原則として、IE が非 iframe にあるときは、doScroll を実行できるかどうかによって DOM が読み込まれているかどうかを継続的に判断することしかできません。この例では、doScroll を 50 ミリ秒ごとに実行しようとします。ページがロードされていないときに doScroll を呼び出すと例外が発生するため、例外をキャッチするために try -catch が使用されます。
(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); } // and execute any waiting functions jQuery.ready(); } })();
5. document.readyState 状态
如果我们注册 ready 函数的时间点太晚了,页面已经加载完成之后,我们才注册自己的 ready 函数,那就用不着上面的层层检查了,直接看看当前页面的 readyState 就可以了,如果已经是 complete ,那就可以直接执行我们准备注册的 ready 函数了。不过 ChrisS 报告了一个很特别的错误情况,我们需要延迟一下执行。
setTimeout 经常被用来做网页上的定时器,允许为它指定一个毫秒数作为间隔执行的时间。当被启动的程序需要在非常短的时间内运行,我们就会给她指定一个很小的时间数,或者需要马上执行的话,我们甚至把这个毫秒数设置为0,但事实上,setTimeout有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的毫秒数设置为0,被调用的程序也没有马上启动。
这个最小的时间间隔是多少呢?这和浏览器及操作系统有关。在John Resig的新书《Javascript忍者的秘密》一书中提到
Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在苹果机上的最小时间间隔是10毫秒,在Windows系统上的最小时间间隔大约是15毫秒),另外,MDC中关于setTimeout的介绍中也提到,Firefox中定义的最小时间间隔(DOM_MIN_TIMEOUT_VALUE)是10毫秒,HTML5定义的最小时间间隔是4毫秒。既然规范都是这样写的,那看来使用setTimeout是没办法再把这个最小时间间隔缩短了。
这样,通过设置为 1, 我们可以让程序在浏览器支持的最小时间间隔之后执行了。
// Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if (document.readyState === "complete") { // 延迟 1 毫秒之后,执行 ready 函数 setTimeout(jQuery.ready, 1); }
6. 完整的代码
在 jQuery 中完整的代码如下所示。位于 jQuery 1.8.3 源代码的 #842 行。
jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); // Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready setTimeout( jQuery.ready, 1 ); // Standards-based browsers support DOMContentLoaded } else if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready 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 ); } // and execute any waiting functions jQuery.ready(); } })(); } } } return readyList.promise( obj ); };
那么,又是谁来调用呢?当然是需要的时候,在我们调用 ready 函数的时候,才需要注册这些判断页面是否完全加载的处理,这段代码在 1.8.3 中位于代码的 #244 行,如下所示:
ready: function( fn ) { // Add the callback jQuery.ready.promise().done( fn ); return this; }
在页面上引用 jQuery 脚本库之后,执行了 jQuery 的初始化函数,初始化函数中创建了 ready 函数。我们在通过 ready 函数注册事件处理之前,jQuery 完成了页面检测代码的注册。这样。当页面完全加载之后,我们注册的函数就被调用了。
补充:jquery ready 简写模式
Jquery ready 函数:
$(document).ready(function(){ alert(' i am ready'); } );
可简写为:
$(function(){ alert("i am in"); } );
希望本文所述对大家jQuery程序设计有所帮助。