首頁  >  文章  >  web前端  >  javascript動態載入實作方法一_javascript技巧

javascript動態載入實作方法一_javascript技巧

WBOY
WBOY原創
2016-05-16 17:50:311421瀏覽

現在也有很多JS動態載入的框架,像是In.js。但這種不是我想要的寫方式,我來說說我的想法。

先來一段java程式碼

複製程式碼 程式碼如下:
User u = new User();
u.show();


依流程就是導包、實例化、呼叫。
JS是做不了導包的,或者說程式碼意義上的導包,一般只是在頁面上進行script標籤的引入。
那麼先假設需要寫成這樣


複製程式碼 程式碼如下:
程式碼如下:


Using("> User");
var u = new User();
u.show();


那麼,在JS裡面可以實現嗎?

來一句的分析,當然,前提是頁面並不用script標籤載入user.js,不然就沒意義了。

第一句

Using("User");

為什麼用Using,當然只是我的一個命名想法而已,可以聯想一下C#,用的就是using ,借來而已。

Using裡面寫入的當然是我需要的物件User,顧名思義,我當然寫成Using("User")了。先不說內裡是怎麼實現的,起碼思路是這樣。
因為我不能模擬關鍵字寫成 Using User;這種起碼我是做不到了。
第二句與第三句複製程式碼
程式碼如下:


var = new User();
u.show();


很正常,就是很平常的實例化與函數調用,唯一不解的是User物件哪裡來的?那當然是第一句導包的時候導入的。


流程就是這麼個流程,那麼到底能不能實現,關鍵就在第一句話。也就是說,到底能不能導包成功,而且該怎麼導包。

從script標籤吸引靈感,對,非同步載入所需的js檔案。
也就是說複製程式碼
程式碼如下:

Using("User") ;

相當於寫了一句複製程式碼
程式碼如下:


現在這麼看下來,這麼做有意義嗎?就為把script標籤寫成JS動態引進的?或者,只為少寫幾個字元?

當然不能,這麼做毫無意義!那要怎麼做?
先從效率來講。
如果一個頁面需要載入N多js檔案的時候,如下
複製程式碼 程式碼如下:








等等等等。

是不是很嚇人,那是相當嚇人,而且後期維護需要很高的成本,有多少頁面,可能需要修改幾個頁面。那麼,當頁面只引入關鍵的幾個js文件,其他文件都採用動態載入的方式呢?
比如我們只需要載入jquery文件,然後調用
複製代碼 代碼如下:

$.getScript("user.js",function(){});

這樣,我們就做到頁面檔案裡面只需要引入
複製程式碼 程式碼如下:



即可。
那麼這種寫法的壞處在哪裡?看一段程式碼
複製程式碼 程式碼如下:

$.getScript("user.js" ,function(){
$.getScript("order.js",function(){
$.getScript("type.js",function(){
$.getScript("validate.js ",function(){
// 與 so on..
});
});
});
});

PS :用In.js的watch函數是可以避免這種情況產生的。這不在本博文的考慮範圍了。

花眼嗎?還願意去對齊程式碼嗎?就算有格式化工具,你還願意將閉合括號與哪個$.getScript對應嗎?當然不願意。
那麼,仿java的導包形式應聲而出。
複製程式碼 程式碼如下:

Using("User");


Using("User");
Using(>
Using("User");
Using(>
Using("User");
Using( "Order");
Using("Type"); Using("Validate"); // and so on.. 或你願意,你可以


複製程式碼


程式碼如下:

Using("User","Type","Order ","Validate",...); 寫法問題無所謂。當然我推薦使用第一種方法,清晰。 導包之後,所有的用法不需要​​任何嵌套,正常使用。


複製程式碼

程式碼如下:

var u = new User(); var> o = new Order(); // and so on.. 但是會提出一個問題。假如非同步的載入都在Using("XXX")的時候執行,那麼


複製程式碼


程式碼如下:

Using("User");
Using("Order");
Using("Type");
Using("Validate");
// and so on ..


複製代碼


代碼如下:
Using("User"); 這個時候一定是不加載,不加載做什麼?當然是回傳一個mock,也就是模擬物件。給使用者先用著,只有當使用者真正需要使用這個物件的時候,再去載入所需的js。也就是說


複製程式碼

程式碼如下:
Using("User");這句話執行完畢之後會創建一個User對象,當時只是個mock var u = new User(); // 這個時候用需要的是真實的User對象實例,就在這個時候去動態加載JS文件,並且回傳已經實例化的User物件 大家都知道,非同步載入是與目前運作的狀態不衝突的,也就是說


複製程式碼
程式碼如下: var u = new User();
這句話執行之後,u是一個沒有實際意義值的變量,而已。那麼,怎麼解決這個問題,我暫且想到的辦法,只能是採用同步策略了。只有當js載入完畢,再去執行之後的js語句,這個地方有點遺憾,而且同步可能帶來的瀏覽器假死,也是一個比較嚴重的問題,暫且不顧這些問題,希望以後能有更好的辦法解決。

那問題出來了,這麼做同步,有什麼優勢嗎?
我不知道有什麼優勢,起碼對比異步加載,應該沒有劣勢。例如正常的非同步載入為
複製程式碼 程式碼如下:

$.getScript("user .js",function(){
var u = new User();
});

單單執行這個語句,要執行到function,本質上也是等user. js載入完畢才會執行,那麼對比
複製程式碼 程式碼如下:
var u = new User();

理論上時間應該相當,因為都是等user.js載入完畢之後才執行的。

起碼第二種看起來更像java式的程式碼,不必理會其他非業務相關的程式碼。

那麼,怎麼會知道需要的物件在什麼地方,怎麼載入進來?我能想到的就是模擬一個配置文件,為什麼用配置文件,而不是像In.js用add函數或其他框架的類似register的函數,大概我只是想用配置文件,更像java,而且後期的修改起來也會更解耦一些吧。

複製程式碼 程式碼如下:
Using.Config = {


Using.Config = {
"" : "/js/user" // 可以隱去.js 因為肯定是載入JS檔了
}

整個思路大概就是這個樣子,我在其基礎上進行了一些約束,例如加入了命名空間複製程式碼
程式碼如下:

var u = new Using.Modules .User();


這樣可以減少一些全域變量,而且有需要的話,可以插入一些所有物件可能都具有的共性,減少創建類別時的重複編碼。

當然,也還是支援不使用命名空間的。
為了解決這個限制的效力,加入了Class.create函數來進行類別建立限制。 複製程式碼
程式碼如下:


Using.Class.create("User",function("User",function( ){
}).property({
}).static({
}).namespace(Using.Modules);


這裡的大概意思是

create(類別名,建構子)
property(類別的屬性)
static(類別的靜態屬性)
namespace(命名空間)

引申到此,為何不加入MVC形式?
後來我發現,要MVC,那麼幾個類之間的動態維護,或者創建之時就由Using這個類來自動維護,暫時還沒想到好的解決辦法,所以沒有加入其中,只能自己創建類,自己維護了.

透過上面的文字,最後得到一個Using.js
然後在頁裡面就只需要引入一個複製程式碼
程式碼如下:



這樣接下來就可以寫複製程式碼
程式碼如下:
Using("jquery");
Using("User");

$("#ID").click(function(){
var user = new User();
user.name = "xx";
user.show();
});
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn