/ JavaScript

How Javascript Loading Works - DOMContentLoaded and OnLoad

The original post from How Javascript Loading Works - DOMContentLoaded and OnLoad

JavaScript的載入是如何運作 - DOMContentLoaded 及 OnLoad

實際上,一個web請求會有三種不同的需求時機,讓我們讀取並執行javascript。這些需求由DOMContentLoaded事件以及OnLoad事件所描繪。我們可以在DOMContentLoaded之前、DOMContentLoaded之後以及OnLoad之後載入我們的腳本。在我深入細節之前,這兩個事件到底是什麼?何時會被觸發?

事件

當頁面的文件物件模型(Document Object Model,DOM)準備好時,就會觸發DOMContentLoaded事件。意思是,頁面中的內容、樣式及結構已經準備好,接受程式碼的請求。綜觀來說,文字、css及html已經準備好 - 但也不是這麼簡單。根據你使用的瀏覽器、HTML版本及樣式表標籤的位置與腳本標籤的位置有所差異,當事件觸發時,CSS可能尚未完成渲染。幸運地,有一種安全且可接受的方式,確保CSS已經載入。就是將外部樣式表的標籤放在頁頭(header),外部javascript的標籤放在頁尾(footer)。這方法強迫javascript只會在外部樣式及HTML內容被載入後才執行。基本上,這表示說如果你將樣式表放在頁頭而javascript放在頁尾,你的DOM將會在DOMContentLoaded觸發之前,載入所有的內容、結構及樣式。這是一件好事!

當整個頁面都已經載入時,就會觸發OnLoad事件。這個就是當你瀏覽器的標題列上的地球或圖示不再旋轉的時候。此時所有的腳本及樣式表都已經載入並且執行,所有圖片也已經下載並顯示。

載入JavaScript

所以我們要如何鉤住每一個事件;更重要的是,我們時候該使用這些事件?為了檢驗不同的事件,讓我們用個簡單的HTML頁,並且輸出結果來看看。

<!DOCTYPE html>
<body>
  <script src="jquery.min.js"></script>
  <script src="external.js"></script>
  <script type='text/javascript'>
    //<![CDATA[
      $.getScript('ajax.js');
      $(document).ready(function(){
        console.log('DOM 已載入 (DOMContentLoaded)');
        $('head').append('<script src="dom.js"></script>');
        $.getScript('dom_ajax.js');
      });
      $(window).load(function(){
        console.log('頁面已載入 (OnLoad)');
        $.getScript('page_ajax.js');
      });
    //]]>
  </script>
</body>

如果我們觀看javascript的控制台,我們會看到類似如下的事件列表:

external.js 已載入並已執行
DOM 已載入 (DOMContentLoaded)
dom.js 已載入並已執行
頁面已載入 (OnLoad)
ajax.js 已載入並已執行
dom_ajax.js 已載入並已執行
page_ajax.js 已載入並已執行

控制台輸出的含意表現了這三個javascript載入的需求:

  • 外部javascript (external.js)在DOMContentLoaded觸發前已經載入
  • 外部javascript在DOMContentLoaded觸發時載入了回呼函式(dom.js),並在OnLoad觸發前插入了HTML
  • AJAX請求並不會使DOMContentLoaded或OnLoad延遲,不論它們是如何被初始的(ajax.js、dom_ajax.js及page_ajax.js)

讓我們看看每一個需求並瞭解哪一個最合適我們的需求。

DOMContentLoaded之前

首先,注意到行內的javascript及外部javascript(external.js)已經載入並立即執行,不論DOM準備好或頁面已經載入。這個已經很明顯,但這是必須在DOMContentLoaded之前執行的程式碼,所以我們可以實際上鉤上這個事件。這個JavaScript最好的理解方式是當作設定(setup)。你不能夠在這時候進行DOM操作,因為它尚未準備好 - 你應該設置你的回呼函式並讓出,剩下的頁面才可以快速的載入。

DOMContentLoaded之後

一旦DOM準備好並可以操作時,腳本(dom.js)就會執行。這裡可以放置你想要更改頁面視覺的程式碼,這是最早可以操作DOM的時機點,並且會在頁面顯示出來之前被執行。這是好事,因為我們不希望讓使用者看到頁面元素不斷跳來跳去或變來變去。

OnLoad之後

一旦頁面完全載入而且使用者可以看到完整的文件之後,腳本(ajax請求及其他在window.load回呼函式裡面的)會被執行。這個地方很適合用來執行需要長時間的程式碼,而且程式碼需要處理頁面的視覺。某些範例,例如分析回報用的函式庫或者較晚才會使用到的程式碼或資料,可以在這先預載起來。Google地圖利用AJAX載入所有的地圖磚,讓頁面不會停頓。

外帶

試著將本文所說的載入流程記在腦海裡,並當你寫程式時回想一下。簡單的佈置程式碼位置,可以帶你獲得巨大的頁面預載速度。我希望這篇文章能夠清楚的說明基本的頁面載入事件並讓你能夠做到更好的決定,知道如何及何時的在你的應用程式中載入javascript。如果你有任何問題或這些方法在使用中的範例,歡迎下評論給我。