window.onload與$(document).ready()的區別

對於初學者來講,window.onload並不陌生,可是對於爲何要使用它、以及不使用它會致使什麼結果,可能並無深究過,下面經過幾個實驗對比,深入理解。瀏覽器

 

實驗一:函數

<script>

  document.getElementById("me").style.color = "blue";

</script>

<body>

  <h1 id="me">Double Zhang</h1>

</body>

 

實驗結果是 h1字體爲原始黑色,並無被渲染爲藍色,爲何代碼沒有生效呢?工具

首先要知道,document文檔是從上向下解析執行,當執行到script時,body中的h1還未被執行和加載到網頁中,這時候 document.getElementById("me")  並無獲取到h1對象,能夠打斷點看一下,獲取的值是undefined,那就更不存在將它的字體設置爲藍色了。性能

 

 

實驗二:測試

<body>

  <script>

    document.getElementById("me").style.color = "blue";

  </script>

  <h1 id="me">Double Zhang</h1>

</body>

 

是否是把script標籤放到body裏就能夠獲取到元素了呢?實驗結果字體依舊是原始的黑色。字體

「document文檔是從上向下解析執行」,當執行script時,h1仍舊沒有被加載。spa

 

 

實驗三:code

<body>

  <h1 id="me">Double Zhang</h1>

  <script>

    document.getElementById("me").style.color = "blue";

  </script>

</body>

 

實驗結果字體爲藍色,終於渲染成功。對象

注意,此次代碼執行的順序有所改變,先將h1標籤渲染進DOM樹,接着纔是經過JS獲取,因此獲取到了該元素,接着改變字體顏色。blog

 

 

實驗四:

<script>

window.onload = function(){   document.getElementById("me").style.color = "blue"; }
</script>

<body>   <h1 id="me">Double Zhang</h1> </body>

 

實驗結果:JS代碼仍是在body標籤前面,講道理這時候是獲取不到h1標籤的,可是此次渲染成功了,字體爲藍色。

仔細看過代碼後發現這次實驗使用了window.onload,這是成功渲染的關鍵,這裏有必要解釋一下window.onload了,它表示:網頁完成了DOM樹的建立以及網頁中圖片等外部資源的加載。其中完成DOM樹的建立能夠保證咱們能經過getElementById方法在DOM樹中找到元素,這就是爲何實驗四可以成功渲染藍色字體。

 

有了這個神器,媽媽不再用擔憂寫在HTML前面的JS代碼獲取不到咱們想要的元素了,不過先別高興的太早,由於這裏存在一個隱患,window.onload中的代碼不只是在DOM樹建立後執行,並且還要等到圖片資源加載完成,那麼當頁面中須要加載的文件(圖片、文本……)很是多的時候,window.onload裏面的代碼就遲遲沒法執行,這將帶來不好的用戶體驗,因而咱們會思考,咱們只是想經過JS代碼操做DOM,與圖片並無關係啊,因此能不能讓DOM樹一建立完成就執行代碼而不用等圖片加載完畢呢?畢竟咱們都想讓本身的網頁性能更好一些、加載更快一些、用戶體驗更好一些,那就接着往下看吧。

 

實驗五:

<script>
  setTimeout(function(){

    document.getElementById("me").style.color = "blue";

  },3000); 

</script>
<body>
  <h1 id="me">Double Zhang</h1>
</body>

 

實驗結果:字體成功渲染爲藍色,並且沒有使用window.onload。

這裏作了一個定時器的3秒延時,在這3秒裏,頁面完成了DOM樹的建立,因此h1元素被成功獲取到了,再添加顏色就沒問題了,可是在這3秒裏該網頁的圖片資源有沒有所有加載完成並不能肯定,不過至少DOM樹是建立完成了,不然實驗結果不會正確。(注意這個3秒的取值是隨便取的,沒有任何規定,純屬測試)

 

細心的人會發現這個實驗有點小問題,運行代碼,會看到字體會閃一下,閃以前爲黑色,閃以後變爲藍色,由於頁面剛呈現時h1默認爲黑色,三秒時代碼生效,字體被設置爲紅色。這種用戶體驗並很差,不知是否能夠改進?

總結一下這種方法的兩大隱患,第一,由於咱們沒法把握DOM樹完成建立的準確時間,就意味着咱們不能避免「閃一下」的問題,和實驗五同樣,假如咱們設置的延遲大於DOM完成建立須要的時間,那頁面就會閃一下;第二,假如咱們設置的setTimeout延遲時間小於DOM樹完成建立須要的時間,DOM未建立好,那麼字體也不會被渲染爲藍色。帶着消除隱患的念頭,接着往下看吧。

 

實驗六:

<script>

$(document).ready(function(){

  document.getElementById("me").style.color = "blue";

});   

</script>
<body>
  <h1 id="me">Double Zhang</h1>
</body>

 

實驗結果:字體成功渲染藍色,使用了jQuery的$.ready()方法。

說到這裏,本篇文章的大BOSS終於出場了(腦中請自行響起BGM)。

$.ready(),它表示:在DOM樹建立完成後(HTML解析的第一步)就觸發代碼,無需等待頁面中其餘資源(圖片等)的加載

到此,以前咱們實驗中遇到的顧慮都被解除了,首先,不用擔憂代碼取不到DOM中想要的元素了,代碼不會再失效了;其次,DOM樹一建立完成就執行了代碼,不用等圖片等資源的加載完成了,效率很高;再次,不用人爲的加定時器去延遲加載了,也就不用擔憂定時器的延遲時間拿捏的準不許了。哎,簡直不要太開心,這麼好的工具,難道不想試着本身造一個嗎?

 

 

本身模擬一個jQuery的ready方法:

function myReady(fn){
  //利用能力檢測區分瀏覽器
  if(document.addEventListener){
    document.addEventListener("DOMContentLoaded",fn,false);
  }
  else{  //這裏是IE低版本瀏覽器
    IEContentLoaded(fn);
  }
  //IE模擬DOMContentLoaded
  function IEContentLoaded(fn){
    var d = document.window;
    //保證fn回調函數只執行一次
    var done = false;
    var init = function(){
      if(!done){
        done = true;
        fn();
      }
    }
    (function(){
      try{
        //DOM樹未建立前調用doScroll會拋出異常
        d.documentElement.doScroll('left');
      }
      catch(e){
        //arguments.callee指向這個便可執行的(function(){})();
        //沒有捕獲異常意味着DOM成功建立,就能夠執行回調函數了
        setTimeout(arguments.callee,60);  
        return;
      }
    })();
    //監聽document的加載狀態
    d.onreadystatechange = function(){
      if(d.readyState == 'complete'){
        d.onreadyState == null;
        init();
      }
    }
  }
}
相關文章
相關標籤/搜索