現在也有很多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");
複製程式碼
程式碼如下:
複製程式碼
程式碼如下:
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。也就是說
複製程式碼
程式碼如下:
複製程式碼
程式碼如下: 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();
});