[転載]document.readyState

33940 ワード

原文:document.readyState
document.onreadystatechange
DOMContentLoaded document.readyStatedocument.onreadystatechangeの組み合わせを用いるjquery readyとwindowをシミュレートすることができる.onloadの効果.ページに大きな画像などのリソースの応答が遅いとwindowになります.onloadイベントはなかなかトリガーできません.だからDOM Ready事件が発生した.このイベントは、DOM文書構造の準備が完了するとトリガー、すなわち、リソースのロード前にトリガーされる.
1. document.readyState
1.1. 概要
DocumentのDocumentreadyStateプロパティは、ドキュメントのロードステータスを説明します.
1.2. 値
ドキュメントのreadyStateは、次のいずれかです.
  • loading/ロード.documentはまだロードされています.
  • interactive/インタラクティブ.ドキュメントはロードが完了し、ドキュメントは解析されましたが、画像、スタイルシート、フレームなどのサブリソースはロードされています.
  • complete/完了.Tドキュメントとすべてのサブリソースのロードが完了しました.ステータスは、loadイベントがトリガーされることを示します.

  • このプロパティの値が変化すると、documentオブジェクト上のreadystatechangeイベントがトリガーされます.
    1.3. 構文
    let string = document.readyState;
    
    // "complete"
    

    1.4. 例
    異なる準備状態
    switch (document.readyState) {
      case "loading":
        // The document is still loading.
        break;
      case "interactive":
        // The document has finished loading.
        // We can now access the DOM elements.
        var span = document.createElement("span");
        span.textContent = "A  element.";
        document.body.appendChild(span);
        break;
      case "complete":
        // The page is fully loaded.
        let CSS_rule = document.styleSheets[0].cssRules[0].cssText;
        console.log(`The first CSS rule is: ${CSS_rule }`);
        break;
    }
    //    DOMContentLoaded/ jquery ready
    document.onreadystatechange = function () {
      if (document.readyState === "interactive") {
        initApplication();
      }
    }
    //    load/onload   
    document.onreadystatechange = function () {
      if (document.readyState === "complete") {
        initApplication();
      }
    }
    

    2. document.onreadystatechange
    2.1. 概要
    ドキュメントのreadystatechangeプロパティが変更されると、readystatechangeイベントがトリガーされます.
    2.2. 構文
    document.onreadystatechange = funcRef;
    
    funcRefは関数参照であり、readystatechangeイベントのトリガ時に呼び出される.
    2.3. 例
    /*
    interactive /   
            ,      ,      ,                。
    https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState
    ​​​​​​​*/
    
    //   DOMContentLoaded  
    
    document.onreadystatechange = function () {
        if (document.readyState === "interactive") {
            initApplication();
        }
    }
    

    3. DOMContentLoaded
    DOMContentLoadedはie 8以下ではサポートされていません.
    DOMContentLoadedはjqueryで使用されています.
    最初のHTMLドキュメントの完全な読み込みと解析が完了すると、スタイルシート、画像、サブフレームの読み込みの完了を待つことなく、DOMContentLoadedイベントがトリガーされます.別の異なるイベントloadは、完全にロードされたページを検出するためにのみ使用されるべきです.DOMContentLoadedの使用がより適切な場合にloadを使用するのは信じられないほど流行しているエラーなので、慎重にしてください.注意:DOMContentLoadedイベントは、scriptが属する前のスタイルシートのロード解析が完了するまでトリガーされません.
    アナログcssファイル:CSS.php
    
    sleep(3);
    

    テストコード:
    <link rel="stylesheet" href="css.php">
    <script>
    document.addEventListener('DOMContentLoaded',function(){
        console.log('3 seconds passed');
    });
    script>
    

    linkをscriptに置くと、すぐに印刷されます.
    Note:同期JavaScriptはDOMの解析を一時停止します.Note:DOMが準備されているかどうかを検出するためにブラウザ間で方法を提供する汎用および独立したライブラリもたくさんあります.
    3.1. 加速中
    DOMがユーザーがページを要求した後にできるだけ早く解析したい場合は、JavaScriptを非同期化し、スタイルシートのロードを最適化し、並列ロードによってページのロードを遅くし、メインhtmlドキュメントからトラフィックを「盗む」ことができます.
    3.2. 例
    <script>
      document.addEventListener("DOMContentLoaded", function(event) {
          console.log("DOM fully loaded and parsed");
      });
    </script>
    <script>
      document.addEventListener("DOMContentLoaded", function(event) {
          console.log("DOM fully loaded and parsed");
      });
    
      for(var i=0; i<1000000000; i++){
          //          DOM   。
          //   DOMContentLoaded       。
      } 
    </script>
    
    

    4. jquey.ready実装
    参考:jQuery deferred.resolveWith()メソッド
    jQuery.holdReady()メソッド
    4.1. readyListなどのIDの定義
  • readyList:実行されるコールバック関数キュー.
  • isReady:DOM readyが識別
  • を完了したかどうか
  • readyWait:
  • holdReady:jQuery.holdReady()メソッド
  • var
        // The deferred used on DOM ready
        //      DOM ready           
        readyList,
        
        // Is the DOM ready to be used? Set to true once it occurs.
        // DOM ready       
        isReady: false,
    
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        //        holdReady       Dom ready     
        readyWait: 1,
        
        // Hold (or release) the ready event
        //           jQuery   ready   
        // example.       ,        。
        //
        // $.holdReady(true);
        // $.getScript("myplugin.js", function() {
        //   $.holdReady(false);
        // });
        //
        holdReady: function(hold) {
            if (hold) {
                jQuery.readyWait++;
            } else {
                jQuery.ready(true);
            }
        },
    

    4.2. ready定義
    // Handle when the DOM is ready
    ready: function(wait) {
        // Abort if there are pending holds or we're already ready
        //       ,holdReady()   , hold     1,      0,       hold ,return 
        //        ,      Ready  ,    ready  ,       。       done        
        if (wait === true ? --jQuery.readyWait : jQuery.isReady) {
            return;
        }
    
        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
        //    body   
        if (!document.body) {
            //    body      ,DOMContentLoaded    ,  
            //   jQuery.ready       setTimeout  
            //         setTimeout(a)     setTimeout(a,0)
            //             jQuery.ready
            //    javascript          
            // setTimeout(jQuery.ready)             ,    DOMContentLoaded       jQuery.ready
            //          :  setTimeout       ,      DOM        
            return setTimeout(jQuery.ready);
        }
    
        // Remember that the DOM is ready
        //    DOM ready     
        jQuery.isReady = true;
    
        // If a normal DOM Ready event fired, decrement, and wait if need be
        // wait   false   ready      ,   return
        if (wait !== true && --jQuery.readyWait > 0) {
            return;
        }
    
        // If there are functions bound, to execute
        //       ,          (    done  ,       document,        jQuery。
        readyList.resolveWith(document, [jQuery]);
    
        // Trigger any bound ready events
        //   jQuery        ready  
        //   :
        //    $(document).on('ready', fn2);
        //    $(document).ready(fn1);
        //    fn1    ,   ready     fn2     
        if (jQuery.fn.trigger) {
            jQuery(document).trigger("ready").off("ready");
        }
    },
    

    4.3. 実行
    実は論理は複雑ではなく、異なるブラウザと互換性を持つためです.
    // $.ready()
    jQuery.ready.promise = function(obj) {
        if (!readyList) {
    
            //     ,     Deferred   
            // Deferred             ,        ready        
            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 :  setTimeout      ,     DOM       .(   DOMContentLoaded)
                setTimeout(jQuery.ready);
    
                // Standards-based browsers support DOMContentLoaded
                //    DOMContentLoaded      (  ie 6 7 8)
            } else if (document.addEventListener) {
                // Use the handy event callback
                //      document.readyState      complete  ,   readystatechange    document.readyState       
                document.addEventListener("DOMContentLoaded", completed, false);
    
                // A fallback to window.onload, that will always work
                //           ,       
                window.addEventListener("load", completed, false);
    
                // If IE event model is used
                //     IE    (6、7、8)
            } else {
                // Ensure firing before onload, maybe late but safe also for iframes
                document.attachEvent("onreadystatechange", completed);
    
                // A fallback to window.onload, that will always work
                window.attachEvent("onload", completed);
    
                // If IE and not a frame
                // continually check to see if the document is ready
                //     IE      frame  
                var top = false;
    
                try {
                    top = window.frameElement == null && document.documentElement;
                } catch (e) {}
    
                //    IE    iframe
                if (top && top.doScroll) {
                    //            doScrollCheck()
                    (function doScrollCheck() {
                        if (!jQuery.isReady) {
    
                            try {
                                // Use the trick by Diego Perini
                                // http://javascript.nwbox.com/IEContentLoaded/
                                // Diego Perini   2007     ,        IE          ,   doScroll     
                                //        IE    iframe   ,            doScroll    DOM       
                                //        50         doScroll,  ,             ,   doScroll      ,      try - catch      
                                //   DOM     ,     doScroll         ,     $.ready()
                                top.doScroll("left");
                            } catch (e) {
                                return setTimeout(doScrollCheck, 50);
                            }
    
                            // detach all dom ready events
                            detach();
    
                            // and execute any waiting functions
                            jQuery.ready();
                        }
                    })();
                }
            }
        }
        //       deferred  ,           
        //      .done .fail    
        return readyList.promise(obj);
    
        // Populate the class2type map
    };
    
    
    // The ready event handler
    completed = function(event) {
    
        // readyState === "complete" is good enough for us to call the dom ready in oldIE
        if (document.addEventListener || event.type === "load" || document.readyState === "complete") {
            detach();
            jQuery.ready();
        }
    },