( 摘自高性能Javascript )
文檔對象模型(DOM)允許你使用JavaScript 動態(tài)創(chuàng)建HTML的幾乎全部文檔內(nèi)容。其根本在于,<script>元素與頁面其他元素沒有什么不同:引用變量可以通過DOM進(jìn)行檢索,可以從文檔中移動、刪除,也可以被創(chuàng)建.
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "file1.js";
document.getElementsByTagName_r("head")[0].appendChild(script);
新的<script>元素加載file1.js源文件。此文件當(dāng)元素添加到頁面之后立刻開始下載。此技術(shù)的重點在于:無論在何處啟動下載,文件的下載和運(yùn)行都不會阻塞其他頁面處理過程。你甚至可以將這些代碼放在<head>部分而不會對其余部分的頁面代碼造成影響(除了用于下載文件的HTTP 連接)。
當(dāng)文件使用動態(tài)腳本節(jié)點下載時,返回的代碼通常立即執(zhí)行(除了Firefox和Opera,他們將等待此前的所有動態(tài)腳本節(jié)點執(zhí)行完畢)。當(dāng)腳本是“自運(yùn)行”類型時這一機(jī)制運(yùn)行正常,但是如果腳本只包含供頁面其他腳本調(diào)用調(diào)用的接口,則會帶來問題。這種情況下,你需要跟蹤腳本下載完成并準(zhǔn)備妥善的情況??梢允褂脛討B(tài)<script>節(jié)點發(fā)出事件得到相關(guān)信息。
Firefox, Opera, Chorme, IE11+ 和Safari3+會在<script>節(jié)點接收完成之后發(fā)出一個load 事件。你可以監(jiān)聽這一事件,以得到腳本準(zhǔn)備好的通知:
var script = document.createElement("script")
script.type = "text/javascript";
//Firefox, Opera, Chrome, Safari 3+
script.onload = function(){
alert("Script loaded!");
};
script.src = "file1.js";
document.getElementsByTagName_r("head")[0].appendChild(script);
Internet Explorer(IE10及以下版本)支持另一種實現(xiàn)方式,它發(fā)出一個readystatechange事件。<script>元素有一個readyState屬性,它的值隨著下載外部文件的過程而改變。readyState 有五種取值:
- uninitialized: 默認(rèn)狀態(tài)
- loading: 下載開始
- loaded: 下載完成
- interactive: 下載完成但尚不可用
- complete: 所有數(shù)據(jù)已經(jīng)準(zhǔn)備好
微軟文檔上說,在<script>元素的生命周期中,readyState 的這些取值不一定全部出現(xiàn),但并沒有指出哪些取值總會被用到。實踐中,我們最感興趣的是“l(fā)oaded”和“complete”狀態(tài)。Internet Explorer 對這兩個readyState值所表示的最終狀態(tài)并不一致,有時<script>元素會得到“l(fā)oader”卻從不出現(xiàn)“complete”,但另外一些情況下出現(xiàn)“complete”而用不到“l(fā)oaded”。最安全的辦法就是在readystatechange 事件中檢查這兩種狀態(tài),并且當(dāng)其中一種狀態(tài)出現(xiàn)時,刪除readystatechange事件句柄(保證事件不會被處理兩次):
var script = document.createElement("script")
script.type = "text/javascript";
//Internet Explorer
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
alert("Script loaded.");
}
};
script.src = "file1.js";
document.getElementsByTagName_r("head")[0].appendChild(script);
大多數(shù)情況下,你希望調(diào)用一個函數(shù)就可以實現(xiàn)JavaScript 文件的動態(tài)加載。下面的函數(shù)封裝了標(biāo)準(zhǔn)實現(xiàn)和IE 實現(xiàn)所需的功能:
function loadScript(url, callback){
var script = document.createElement ("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName_r("head")[0].appendChild(script);
}