1. 程式人生 > >jQuery ready方法實現

jQuery ready方法實現

很早之前就留下了這個問題,趕上五一放假,好好研究總結一下吧。

  1. 首先jq中ready方法和window的onload方法的不同這裡再提一下,首先ready只是dom樹載入完畢,一些img等資源可能還沒載入完成,而onload則是全部載入成功。而且ready方法可以有多個,而onload只能寫一個。還有一個區別是什麼了,想起來補上。

  2. 一般讓我們手寫模擬一個jq的ready方法,我大多都是這樣寫:

     document.ready = function (callback) {
            ///相容FF,Google
            if (document.addEventListener) {
                        document.addEventListener('DOMContentLoaded', function () {
                            document.removeEventListener('DOMContentLoaded', arguments.callee, false);
                            callback();
                        }, false)
                    }
             //相容IE
            else if (document.attachEvent) {
                document.attachEvent('onreadystatechange', function () {
                      if (document.readyState == "complete") {
                                document.detachEvent("onreadystatechange", arguments.callee);
                                callback();
                       }
                })
            }
            else if (document.lastChild == document.body) {
                callback();
            }
        }

先檢測DOMContentLoaded事件,然後撤銷繫結,在觸發回撥,IE的就是檢測onreadystatechange事件,如果document.readyState == "complete"就老樣子先撤銷繫結事件,最後觸發回撥,最後就是一個退化操作。

  1. ready方法出現的原因就是window.onload事件是在頁面所有的資源都載入完畢後觸發的. 如果頁面上有大圖片等資源響應緩慢, 會導致window.onload事件遲遲無法觸發.所以出現了DOM Ready事件. 此事件在DOM文件結構準備完畢後觸發, 即在資源載入前觸發.

  2. 一般在主流瀏覽器,DOMContentLoaded 事件在許多Webkit瀏覽器以及IE9上都可以使用, 此事件會在DOM文件準備好以後觸發, 包含在HTML5標準中. 對於支援此事件的瀏覽器, 直接使用DOMContentLoaded事件是最簡單最好的選擇.但是IE6,7,8都不支援DOMContentLoaded事件。

這裡寫圖片描述

在上面程式碼中也就是這樣寫的,第一檢測的還是DOMContentLoaded事件,而且老版本瀏覽器或者IE6-8中,hack的方法就不知一種了:

  • 上面也寫到的readyState: 如果瀏覽器存在 document.onreadystatechange 事件,當該事件觸發時,如果 document.readyState=complete 的時候,可視為 DOM 樹已經載入。
    eg:
    //onreadystatechange event
    document.onreadystatechange = function(e){
        document.getElementById("divMsg").innerHTML += "<br/> onreadystatechange, readyState:" + document.readyState;
     
    };
  • doScroll檢測:IE瀏覽器文件中說明,當頁面 DOM 未載入完成時,呼叫 doScroll 方法時,會產生異常。(微軟的文件指出doScroll必須在DOM主文件準備完畢時才可以正常觸發)那麼我們反過來用,如果不異常,那麼就是頁面DOM載入完畢了,可以不斷地通過能否執行 doScroll 判斷 DOM 是否載入完畢
    //doScroll
    var doScrollMoniterId = null;
    var doScrollMoniter = function(){
        try{
            document.documentElement.doScroll("left");
            document.getElementById("divMsg").innerHTML += "<br/>doScroll, readyState:" + document.readyState;
            if(doScrollMoniterId){
                clearInterval(doScrollMoniterId);
            }
        }
        catch(ex){
        }
    }
    doScrollMoniterId = setInterval(doScrollMoniter, 1);
  • setTimeout : 在setTimeout中觸發的函式, 一定會在DOM準備完畢後觸發.
var setTimeoutReady = function(){
    document.getElementById("divMsg").innerHTML += "<br/> setTimeout , readyState:" + document.readyState;
};
var setTimeoutBindReady = function(){
    /in/.test(document.readyState)?setTimeout(arguments.callee, 1):setTimeoutReady();
};
setTimeoutBindReady();
  • 外部script: 通過設定了script塊的defer屬性實現.詳見:連結
  • 內部script: 外部script的改進版本. 外部script需要頁面引用額外的js檔案. 內部script方法可以避免此問題。詳見:連結

上面的一些方法其實也存在問題,比如readyState狀態為complete的時候圖片已經載入完了。
所以引自一個大佬的說法就是:
這裡寫圖片描述

具體使用doScroll的話上次看到了這種寫法:

//為了保證最後一定會呼叫ready方法,在上面每一種方式的最後都還是會為load事件繫結ready方法。
if ( document.readyState === "complete" ) {
      // Handle it asynchronously to allow scripts the opportunity to delay ready
      //這裡的setTimeout是為了非同步
      setTimeout( jQuery.ready, 1 );

    // Standards-based browsers support DOMContentLoaded
    //標準瀏覽器偵聽事件介面:document.addEventListener
    } else if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

      // A fallback to window.onload, that will always work
      //文章一開始說了,這裡為了保證一定會觸發ready,所以還針對onload也繫結一次回撥
      window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else {
      //IE偵聽事件介面:document.attachEvent
      //如果有onreadystatechange事件,偵聽之
      // 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 );


      // http://javascript.nwbox.com/IEContentLoaded/
      // 見下邊說明
      // 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) {}

      //如果是IE並且不是iframe
      if ( top && top.doScroll ) {
        (function doScrollCheck() {
          if ( !jQuery.isReady ) {

            try {
              // Use the trick by Diego Perini
              // http://javascript.nwbox.com/IEContentLoaded/
              //一直呼叫doScroll滾動,因為DOM渲染結束前,DOM節點是沒有doScroll方法的,所以一直會異常
              //直到DOM渲染結束了,這個時候doScroll方法不會丟擲異常,然後就呼叫$.ready()
              top.doScroll("left");
            } catch(e) {
              return setTimeout( doScrollCheck, 50 );
            }

            // and execute any waiting functions
            jQuery.ready();
          }
        })();
      }
    }

上面的程式碼即實現這樣的流程:
這裡寫圖片描述

jQuery原始碼的實現稍有複雜,等日後分析懂了繼續補充。

相關推薦

jQuery ready方法實現

很早之前就留下了這個問題,趕上五一放假,好好研究總結一下吧。 首先jq中ready方法和window的onload方法的不同這裡再提一下,首先ready只是dom樹載入完畢,一些img等資源可能還沒載入完成,而onload則是全部載入成功。而且ready方法可以有多個,而onload只能寫一個。還有一個區別

JS原生方法實現JQuery ready()方法

首先說明一下load事件與ready事件的區別 HTML文件載入順序: ①       解析HTML結構 ②       載入外部指令碼和樣式表文件 ③       解析並執行指令碼程式碼 ④       構造HTML DOM模型 ⑤       載入圖片等外部檔

jquery load()方法實現區域性重新整理,多張網頁切換(li標籤實現上下頁的切換)

---學習借鑑中--- (1)父頁面插入的位置 <div  id="content" > //id為要重新整理顯示的子頁面的內容 </div> (2)父頁面顯示標籤切換不同html頁面 <ul class="userMenu"> <li

Jquery load()方法 實現公用頭部 尾部

//這是header.html裡的程式碼,想作為頭部引進來 <div id="loginBox"> <span></span> <div> <div> &l

jQuery load() 方法實現載入遠端資料

jQuery load() 方法是簡單但強大的 AJAX 方法。load() 方法從伺服器載入資料,並把返回的資料放入被選元

跨域問題相關知識詳解(原生js和jquery兩種方法實現jsonp跨域)

syn con 加載 developer 兩種方法 ray exe 編寫 分組 1、同源策略 同源策略(Same origin policy),它是由Netscape提出的一個著名的安全策略。同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽

簡單的實現圖片預覽, 通過原生ajax以及 jQuery兩種方法實現圖片預覽,有更好的辦法可以留言喔................

XML HP OS image end php代碼 append sda ext 1.原生寫ajax實現圖片預覽:   結構:     <input type="file">       <img src="" > JavaScri

JQuery擴展方法實現Form表單與Json互相轉換

val adjust new 映射 checked josn fin pop undefined JQuery筆記 記兩段代碼,使用JQuery實現從表單獲取json與後端交互,以及把後端返回的json映射到表單相應的字段上。 把表單轉換出json對象 //把表單

Tab切換欄(jQuery方法實現)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style ty

javascript事件委託理解,jQuery on 方法一步到位實現事件委託

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

JqueryReady方法載入為什麼兩次?

Ready方法會呼叫兩次? 檢視對應的頁面是否存在<iframe src="#" ……> 存在iframe載入這個頁面的時候,頁面就會載入兩次。 $(document).ready(function(){}和onload的區別? 頁面載入完成有兩種事件: 區別

jQuery中toggle方法實現切換

首先定義myToggle 方法:   $.prototype["myToggle"] = function () {     var args = arguments;     var that = this;     var i = 0;     var n =

Javascript中onload方法Jqueryready方法的區別

1.執行時間 window.onload必須等到頁面內包括圖片的所有元素載入完畢後才能執行。 $(document).ready()是DOM機構繪製完畢後就執行,不必等到載入完畢。 2.編寫個數不同 window.onload不能同時編寫多個,且多個只能執行一個。 $(document).r

jQuery: 使用setInterval()方法實現考試系統的自動提交(ASP.NET)

 需求: 要實現考試系統在超過規定的時間後自動提交。 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title

jQuery的toggle方法實現元素的左右滑動隱藏

通常情況下給元素加toggle方法通常會是上下滑動隱藏,而有時我們又需要左右滑動隱藏怎麼辦呢? JS片段: $(document).ready(function(){ $('#example

jQuery使用JSONP實現跨域獲取資料的三種方法詳解

本文例項講述了jQuery使用JSONP實現跨域獲取資料的三種方法。分享給大家供大家參考,具體如下: 第一種方法是在ajax函式中設定dataType為'jsonp' $.ajax({ dataType: 'jsonp', url: 'http://www.a

37. jQuery- ready()方法的幾種寫法

jquery-ready()方法的四種寫法 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>jQuery- ready()方法的幾種寫法<

52 jQuery-使用fadeIn()和fadeOut()方法實現淡入淡出效果

1.效果圖 2.HTML程式碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>52 jQuery-使用fadeIn()和fadeO

51 jQuery-使用slideDown()與slideUp()方法實現滑動效果

1.效果圖 2.HTML程式碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>51 jQuery-使用slideDown()與sl

jquery的ajax方法實現三級聯動

<script>(function(){var p = $('#province');//得到省份的select物件var c = $('#city');//得到城市的select物件var t = $('#town');//得到地區的select物件$.aja