傳統上,加載Javascript文件都是使用<script>標籤。java
就像下面這樣:api
<script type="text/javascript" src="example.js"></script>數組
<script>標籤很方便,只要加入網頁,瀏覽器就會讀取並運行。可是,它存在一些嚴重的缺陷。瀏覽器
(1)嚴格的讀取順序。因爲瀏覽器按照<script>在網頁中出現的順序,讀取Javascript文件,而後當即運行,致使在多個文件互相依賴的狀況下,依賴性最小的文件必須放在最前面,依賴性最大的文件必須放在最後面,不然代碼會報錯。app
(2)性能問題。瀏覽器採用"同步模式"加載<script>標籤,也就是說,頁面會"堵塞"(blocking),等待javascript文件加載完成,而後再運行後面的HTML代碼。當存在多個<script>標籤時,瀏覽器沒法同時讀取,必須讀取完一個再去讀取另外一個,形成讀取時間大大延長,頁面響應緩慢。異步
爲了解決這些問題,可使用DOM方法,動態加載Javascript文件。函數
function loadScript(url){requirejs
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script);
}
這樣作的原理是,瀏覽器即時創造出一個<script>標籤,而後"異步"讀取Javascript文件。這樣不會形成頁面堵塞,但會形成另一個問題:這樣加載的Javascript文件,不在原始的DOM結構之中,所以在DOM-ready(DOMContentLoaded)事件和window.onload事件中指定的回調函數對它無效。
外部函數庫LABjs和RequireJS,能夠幫助咱們更有效地管理Javascript加載。
下面根據ScriptJunkie的文章,舉一個最簡單的例子,來講明這兩個函數庫的基本用法。更高級的用法,請參閱它們的文檔。
<script src="script1.js"></script>
<script src="script2-a.js"></script>
<script src="script2-b.js"></script>
<script type="text/javascript">
initScript1();
initScript2();
</script>
<script src="script3.js"></script>
<script type="text/javascript">
initScript3();
</script>
上面這段代碼,將依次加載4個javascript文件:script1.js、script2-a.js、script2-b.js和script3.js。在加載完前三個文件後,運行兩個函數initScript1()和initScript2();加載完第四個文件後,再運行函數initScript3()。
下面,用LABjs對其進行改寫:
<script src="LAB.js"></script>
<script type="text/javascript">
$LAB
.script("script1.js").wait()
.script("script2-a.js")
.script("script2-b.js")
.wait(function(){
initScript1();
initScript2();
})
.script("script3.js")
.wait(function(){
initScript3();
});
</script>
首先,$LAB對象替代了<script>標籤,而後.script()方法表示加載Javascript文件,不帶參數的.wait()方法表示當即運行剛纔加載的Javascript文件,帶參數的.wait()方法也是當即運行剛纔加載的Javascript文件,可是還運行參數中指定的函數。
這裏須要注意的是,能夠同時運行多條$LAB鏈,可是它們之間是徹底獨立的,不存在次序關係。若是你要確保一個Javascript文件在另外一個文件以後運行,你只能把它們寫在同一個鏈操做之中。只有當某些腳本是徹底無關的時候,你才應該考慮把它們分紅不一樣的$LAB鏈,表示它們之間不存在相關關係。
接下來是requireJS的改寫:
<script src="require.js"></script>
<script type="text/javascript">
require([
"script1.js",
"script2-a.js",
"script2-b.js",
"script3.js"],
function(){
initScript1();
initScript2();
initScript3();}
);
</script>
require()接受兩個參數,第一個數組表示所要加載的Javascript文件,第二個是加載完成後所要運行的回調函數。原生的require()不支持按次序加載,因此四個Javascript文件到底先加載哪一個,沒法事前知道,require()只保證這四個文件所有加載完成以後,纔會運行所指定的回調函數。
若是按次序加載對你很重要,你可使用官方提供的order插件。
(完)