2011-08-18 98 views
6

懶惰加載js或ondemand加載的3種方式與原因有什麼區別?懶加載javascript

腳本1:

$.getScript = function(url, callback, cache){ 
    $.ajax({ 
     type: "GET", 
     url: url, 
     success: callback, 
     dataType: "script", 
     cache: cache 
    }); 
}; 

SCRIPT2:

function require(file, callback) { 
    var script = document.getElementsByTagName('script')[0], 
     newjs = document.createElement('script'); 

    // IE 
    newjs.onreadystatechange = function() { 
     if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') { 
      callback(); 
     } 
    }; 

    // others 
    newjs.onload = function() { 
     callback(); 
    }; 

    newjs.src = file; 
    script.parentNode.insertBefore(newjs, script); 
} 

document.getElementById('id').onclick = function() { 
    require('ondemand.js', function() { 
     extraFunction('loaded from the parent page'); 
     document.body.appendChild(document.createTextNode('done!')); 
    }); 
}; 

script3:

$L = function (c, d) { 
    for (var b = c.length, e = b, f = function() { 
      if (!(this.readyState 
        && this.readyState !== "complete" 
        && this.readyState !== "loaded")) { 
       this.onload = this.onreadystatechange = null; 
       --e || d() 
      } 
     }, g = document.getElementsByTagName("head")[0], i = function (h) { 
      var a = document.createElement("script"); 
      a.async = true; 
      a.src = h; 
      a.onload = a.onreadystatechange = f; 
      g.appendChild(a) 
     }; b;) i(c[--b]) 
}; 
+0

如果你寫了這些函數,我希望你認識到'readyState =='loaded''發生在執行腳本之前,而'* complete''發生在*之後。 – zzzzBov

+0

是的真的......即使我只是解析腳本而不是執行,因爲執行需要比解析更多的時間 – paul

回答

7
  1. 使用AJAX來加載腳本。更具體地說,它使用XHR來加載一些js並使其可供瀏覽器使用。沒有阻塞完成。它仍然執行相同的來源政策。
  2. 通過創建<script/>元素來修改頭文件以注入新的.js文件。這也不會阻止頁面加載時的瀏覽器。
  3. 是否與#2一樣,但它似乎支持一組腳本。它還將async設置爲true,不會導致阻塞。 for循環更令人困惑,因爲它創建了更多的匿名方法。
+0

謝謝...很好地描述了 – paul

+0

當我們注入腳本沒有AJAX時有沒有緩存的問題?函數1,因爲它的XHR我們可以指定緩存:緩存 – paul

+0

我認爲他們都可能有這個問題。瀏覽器甚至可以緩存xhr請求。您可以使用隨機查詢來分解緩存。如果你控制服務器,那麼你可以選擇不緩存。 –

2
  1. 似乎有一個XMLHttpRequest和eval()它來獲取腳本。如果腳本不在相同的協議/域/端口上,這將不起作用。

  2. 和3.似乎都做同樣的事情:他們創建一個<script src="the script url"></script>元素,綁定onload事件並將其插入頁面。該腳本在加載後由瀏覽器執行,並觸發onload事件。

+0

您對緩存有什麼看法?因爲在第一個函數中,我可以傳遞一個屬性緩存:緩存,而對於其他兩種情況會是一個問題? – paul

+0

這兩種方法都緩存友好,只要服務器發送正確的標題 – arnaud576875

1

你應該試試這個所謂的新圖書館head.js

他們有一些有趣的想法和API ..希望它幫助。

或者你可以做的是使用正常的xhr請求來獲取你的腳本文件名並使用像這樣的方法插入dom ..我也添加了removeScript部分。

addScript = function(file) 
{ 
    var headID = document.getElementsByTagName("head")[0];   
    var newScript = document.createElement('script'); 
    newScript.type = 'text/javascript'; 
    newScript.src = file; 
    headID.appendChild(newScript); 
}; 
removeScript = function(file) 
{ 
    var headID = document.getElementsByTagName("head")[0].children; 
    for(var i in headID) 
     if(headID[i].tagName == "SCRIPT") 
      if(headID[i].getAttribute('src') == file) 
       headID[i].parentNode.removeChild(headID[i]); 
} 

如果您正在使用像jQuery庫你不需要擔心什麼,你可以從服務器獲取的HTML或腳本標記,並插入它使用的.html()API來爲DOM

+0

這應該是一個評論,因爲它沒有真正回答任何問題。 –

+0

感謝您的信息。 :/ – Baz1nga

+0

@zzzz yes通過head.js,labjs和controljs查看,但試圖想出我自己的解決方案,而不是使用另一個庫 – paul

2
  1. 通過AJAX獲取腳本,eval()的內容
  2. 插入script元件到head元件並報告時,它已經加載
  3. 同(2),但接受和腳本URL的陣列s和被方式更爲複雜寫入

(2)和(3)兩者都使用onreadystatechange鉤,其可能不與舊的瀏覽器(兼容例如,火狐3.x和下面不支持它)。 (1)可能是最強大的,兼容性明智的,因爲它只需要XHR。但是,如果您在以這種方式加載的代碼中出現錯誤,那麼瀏覽器的控制檯可能不會很有幫助,因爲錯誤只出現在「評估代碼」中,而不是在特定的文件/行中。也就是說,延遲加載通常是一種優化,因此您可以在調試時正常包含腳本,或者使用其他兩種方法。