javascript動(dòng)態(tài)加載實(shí)現(xiàn)方法一
更新時(shí)間:2012年08月22日 21:27:52 作者:
這兩天,沒什么太多的事情,好吧,我承認(rèn),是我這兩天不想做公司的項(xiàng)目,因?yàn)槲彝话l(fā)奇想,其實(shí)也不算突發(fā)奇想,算是對(duì)以前的想法的實(shí)現(xiàn),就是把JS當(dāng)做Java來寫
現(xiàn)在也有很多JS動(dòng)態(tài)加載的框架,比如In.js。但是這種并不是我想要的編寫方式,我來說說我的想法。
先來一段java代碼
import Biz.User;
User u = new User();
u.show();
按流程就是導(dǎo)包、實(shí)例化、調(diào)用。
JS是做不了導(dǎo)包的,或者說代碼意義上的導(dǎo)包,一般只是在頁面上進(jìn)行script標(biāo)簽的引入。
那么 先假設(shè)需要寫成這樣
Using("User");
var u = new User();
u.show();
那么,在JS里面可以實(shí)現(xiàn)嗎?
來一句一句的分析,當(dāng)然,前提是頁面并不用script標(biāo)簽載入user.js,不然就沒意義了。
第一句
Using("User");
為什么用Using,當(dāng)然只是我的一個(gè)命名想法而已,可以聯(lián)想一下C#,用的就是using,借來而已。
Using里面寫入的當(dāng)然是我需要的對(duì)象User,顧名思義,我當(dāng)然寫成Using("User")了。先不說內(nèi)里是怎么實(shí)現(xiàn)的,起碼思路是這樣。
因?yàn)椴荒苣M關(guān)鍵字寫成 Using User;這種起碼我是做不到了。
第二句和第三句
var u = new User();
u.show();
很正常,就是很平常的實(shí)例化與函數(shù)調(diào)用,唯一不解的是User對(duì)象哪里來的?那么當(dāng)然是第一句導(dǎo)包的時(shí)候?qū)氲摹?
流程就是這么個(gè)流程,那么到底能不能實(shí)現(xiàn),關(guān)鍵就在第一句話。也就是說,到底能不能導(dǎo)包成功,而且該怎么導(dǎo)包。
從script標(biāo)簽吸引靈感,對(duì),異步加載所需要的js文件。
也就是說
Using("User");
相當(dāng)于寫了一句
現(xiàn)在這么看下來,這么做有意義嗎?就為把script標(biāo)簽寫成JS動(dòng)態(tài)引入的?或者,只為少寫幾個(gè)字符?
當(dāng)然不能,這么做毫無意義!那要怎么做?
先從效率來講。
如果一個(gè)頁面需要載入N多js文件的時(shí)候,如下
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="view.js"></script>
<script type="text/javascript" src="register.js"></script>
<script type="text/javascript" src="validate.js"></script>
<script type="text/javascript" src="user.js"></script>
<script type="text/javascript" src="order.js"></script>
<script type="text/javascript" src="type.js"></script>
等等等等。
是不是很嚇人,那是相當(dāng)嚇人,而且后期維護(hù)需要很高的成本,有多少頁面,可能就需要修改幾個(gè)頁面。那么,當(dāng)頁面只引入關(guān)鍵的幾個(gè)js文件,其他文件都采用動(dòng)態(tài)載入的方式呢?
比如我們只需要載入jquery文件,然后調(diào)用
$.getScript("user.js",function(){});
這樣,我們就做到頁面文件里面只需要引入
<script type="text/javascript" src="jquery.min.js"></script>
即可。
那么這種寫法的壞處在哪里?看一段代碼
$.getScript("user.js",function(){
$.getScript("order.js",function(){
$.getScript("type.js",function(){
$.getScript("validate.js",function(){
// and so on..
});
});
});
});
PS:用In.js的watch函數(shù)是可以避免這種情況產(chǎn)生的。這不在本博文的考慮范圍了。
花眼嗎?還愿意去對(duì)齊代碼嗎?即便有格式化工具,你還愿意將閉合括號(hào)與哪個(gè)$.getScript對(duì)應(yīng)嗎?當(dāng)然不愿意。
那么,仿java的導(dǎo)包形式應(yīng)聲而出。
Using("User");
Using("Order");
Using("Type");
Using("Validate");
// and so on..
或者你愿意,你可以
Using("User","Type","Order","Validate",...);
寫法問題 無所謂。當(dāng)然我推薦使用第一種方法,清晰。
導(dǎo)包之后,所有的用法不需要任何嵌套,正常使用。
var u = new User();
var o = new Order();
// and so on..
但是會(huì)提出一個(gè)問題。假如異步的加載都在Using("XXX")的時(shí)候執(zhí)行,那么
Using("User");
Using("Order");
Using("Type");
Using("Validate");
// and so on..
這一段我就需要異步載入4個(gè)文件,雖然是異步的,但是未免有些麻煩?而且需要?jiǎng)?chuàng)建4個(gè)鏈接。你愿意合并JS的話,也可以。而且,Using的時(shí)候我是不需要使用對(duì)象的,這個(gè)時(shí)候未免太浪費(fèi)資源了?
至于這個(gè)問題,我的解決辦法就是學(xué)習(xí)hibernate,延遲加載,按需加載。
那么怎么做呢?
Using("User");
這個(gè)時(shí)候肯定是不加載,不加載做什么?當(dāng)然是返回一個(gè)mock,也就是模擬對(duì)象。給用戶先用著,只有當(dāng)用戶真正需要使用這個(gè)對(duì)象的時(shí)候,再去加載所需的js。也就是說
Using("User"); // 這句話執(zhí)行完畢之后會(huì)創(chuàng)建一個(gè)User對(duì)象,當(dāng)時(shí)僅僅是個(gè)mock
var u = new User(); // 這個(gè)時(shí)候用需要的是真實(shí)的User對(duì)象實(shí)例,就在這個(gè)時(shí)候去動(dòng)態(tài)加載JS文件,并且返回已經(jīng)實(shí)例化的User對(duì)象
大家都知道,異步加載是與當(dāng)前運(yùn)行的狀態(tài)不沖突的,也就是說
var u = new User();
這句話執(zhí)行之后,u是一個(gè)沒有實(shí)際意義值的變量,而已。那么,怎么解決這個(gè)問題,我暫且想到的辦法,只能是采用同步策略了。只有當(dāng)js加載完畢,再去執(zhí)行之后的js語句,這個(gè)地方有點(diǎn)遺憾,而且同步可能帶來的瀏覽器假死,也是一個(gè)比較嚴(yán)重的問題,暫且不顧這些問題,希望以后能有更好的辦法解決。
那問題出來了,這么做同步,有什么優(yōu)勢(shì)嗎?
我不知道有什么優(yōu)勢(shì),起碼對(duì)比異步加載,應(yīng)該沒有劣勢(shì)。比如正常的異步加載為
$.getScript("user.js",function(){
var u = new User();
});
單單執(zhí)行這個(gè)語句,要執(zhí)行到function,本質(zhì)上也是等user.js加載完畢才會(huì)執(zhí)行,那么對(duì)比
var u = new User();
理論上時(shí)間應(yīng)該相當(dāng),因?yàn)槎际堑萿ser.js加載完畢之后才執(zhí)行的。
起碼第二種看起來更像java式的代碼,不必理會(huì)其他非業(yè)務(wù)相關(guān)的代碼。
那么,怎么會(huì)知道需要的對(duì)象在什么地方,怎么加載進(jìn)來?我能想到的就是模擬一個(gè)配置文件,為什么用配置文件,而不是像In.js用add函數(shù)或者其他框架的類似于register的函數(shù),大概我只是想用配置文件,更像java,而且后期的修改起來也會(huì)更解耦一些吧。
Using.Config = {
"User" : "/js/user" // 可以隱去.js 因?yàn)榭隙ㄊ羌虞dJS文件了
}
整個(gè)思路大概就是這個(gè)樣子,我在其基礎(chǔ)上進(jìn)行了一些約束,比如加入了命名空間
var u = new Using.Modules.User();
這樣可以減少一些全局變量,而且有需要的話,可以插入一些所有對(duì)象可能都具有的共性,減少創(chuàng)建類時(shí)的重復(fù)編碼。
當(dāng)然,也還是支持不使用命名空間的。
為了解決這個(gè)約束的效力,加入了Class.create函數(shù)來進(jìn)行類創(chuàng)建約束。
Using.Class.create("User",function(){
}).property({
}).static({
}).namespace(Using.Modules);
這里的大概意思就是
create(類名,構(gòu)造函數(shù))
property(類的屬性)
static(類的靜態(tài)屬性)
namespace(命名空間)
引申到此,為何不加入MVC形式?
后來我發(fā)現(xiàn),要MVC,那么幾個(gè)類之間的動(dòng)態(tài)維護(hù),或者創(chuàng)建之時(shí)就由Using這個(gè)類來自動(dòng)維護(hù),暫時(shí)還沒想到好的解決辦法,所以沒有加入其中,只能自己創(chuàng)建類,自己維護(hù)了.
通過上面的文字,最后得到一個(gè)Using.js
然后在頁面里面就只需要引入一個(gè)
<script type="text/javascript" src="using.js"></script>
這樣接下來就可以寫
Using("jquery");
Using("User");
$("#ID").click(function(){
var user = new User();
user.name = "xx";
user.show();
});
先來一段java代碼
復(fù)制代碼 代碼如下:
import Biz.User;
User u = new User();
u.show();
按流程就是導(dǎo)包、實(shí)例化、調(diào)用。
JS是做不了導(dǎo)包的,或者說代碼意義上的導(dǎo)包,一般只是在頁面上進(jìn)行script標(biāo)簽的引入。
那么 先假設(shè)需要寫成這樣
復(fù)制代碼 代碼如下:
Using("User");
var u = new User();
u.show();
那么,在JS里面可以實(shí)現(xiàn)嗎?
來一句一句的分析,當(dāng)然,前提是頁面并不用script標(biāo)簽載入user.js,不然就沒意義了。
第一句
Using("User");
為什么用Using,當(dāng)然只是我的一個(gè)命名想法而已,可以聯(lián)想一下C#,用的就是using,借來而已。
Using里面寫入的當(dāng)然是我需要的對(duì)象User,顧名思義,我當(dāng)然寫成Using("User")了。先不說內(nèi)里是怎么實(shí)現(xiàn)的,起碼思路是這樣。
因?yàn)椴荒苣M關(guān)鍵字寫成 Using User;這種起碼我是做不到了。
第二句和第三句
復(fù)制代碼 代碼如下:
var u = new User();
u.show();
很正常,就是很平常的實(shí)例化與函數(shù)調(diào)用,唯一不解的是User對(duì)象哪里來的?那么當(dāng)然是第一句導(dǎo)包的時(shí)候?qū)氲摹?
流程就是這么個(gè)流程,那么到底能不能實(shí)現(xiàn),關(guān)鍵就在第一句話。也就是說,到底能不能導(dǎo)包成功,而且該怎么導(dǎo)包。
從script標(biāo)簽吸引靈感,對(duì),異步加載所需要的js文件。
也就是說
復(fù)制代碼 代碼如下:
Using("User");
相當(dāng)于寫了一句
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="user.js"></script>
現(xiàn)在這么看下來,這么做有意義嗎?就為把script標(biāo)簽寫成JS動(dòng)態(tài)引入的?或者,只為少寫幾個(gè)字符?
當(dāng)然不能,這么做毫無意義!那要怎么做?
先從效率來講。
如果一個(gè)頁面需要載入N多js文件的時(shí)候,如下
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="view.js"></script>
<script type="text/javascript" src="register.js"></script>
<script type="text/javascript" src="validate.js"></script>
<script type="text/javascript" src="user.js"></script>
<script type="text/javascript" src="order.js"></script>
<script type="text/javascript" src="type.js"></script>
等等等等。
是不是很嚇人,那是相當(dāng)嚇人,而且后期維護(hù)需要很高的成本,有多少頁面,可能就需要修改幾個(gè)頁面。那么,當(dāng)頁面只引入關(guān)鍵的幾個(gè)js文件,其他文件都采用動(dòng)態(tài)載入的方式呢?
比如我們只需要載入jquery文件,然后調(diào)用
復(fù)制代碼 代碼如下:
$.getScript("user.js",function(){});
這樣,我們就做到頁面文件里面只需要引入
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="jquery.min.js"></script>
即可。
那么這種寫法的壞處在哪里?看一段代碼
復(fù)制代碼 代碼如下:
$.getScript("user.js",function(){
$.getScript("order.js",function(){
$.getScript("type.js",function(){
$.getScript("validate.js",function(){
// and so on..
});
});
});
});
PS:用In.js的watch函數(shù)是可以避免這種情況產(chǎn)生的。這不在本博文的考慮范圍了。
花眼嗎?還愿意去對(duì)齊代碼嗎?即便有格式化工具,你還愿意將閉合括號(hào)與哪個(gè)$.getScript對(duì)應(yīng)嗎?當(dāng)然不愿意。
那么,仿java的導(dǎo)包形式應(yīng)聲而出。
復(fù)制代碼 代碼如下:
Using("User");
Using("Order");
Using("Type");
Using("Validate");
// and so on..
或者你愿意,你可以
復(fù)制代碼 代碼如下:
Using("User","Type","Order","Validate",...);
寫法問題 無所謂。當(dāng)然我推薦使用第一種方法,清晰。
導(dǎo)包之后,所有的用法不需要任何嵌套,正常使用。
復(fù)制代碼 代碼如下:
var u = new User();
var o = new Order();
// and so on..
但是會(huì)提出一個(gè)問題。假如異步的加載都在Using("XXX")的時(shí)候執(zhí)行,那么
復(fù)制代碼 代碼如下:
Using("User");
Using("Order");
Using("Type");
Using("Validate");
// and so on..
這一段我就需要異步載入4個(gè)文件,雖然是異步的,但是未免有些麻煩?而且需要?jiǎng)?chuàng)建4個(gè)鏈接。你愿意合并JS的話,也可以。而且,Using的時(shí)候我是不需要使用對(duì)象的,這個(gè)時(shí)候未免太浪費(fèi)資源了?
至于這個(gè)問題,我的解決辦法就是學(xué)習(xí)hibernate,延遲加載,按需加載。
那么怎么做呢?
復(fù)制代碼 代碼如下:
Using("User");
這個(gè)時(shí)候肯定是不加載,不加載做什么?當(dāng)然是返回一個(gè)mock,也就是模擬對(duì)象。給用戶先用著,只有當(dāng)用戶真正需要使用這個(gè)對(duì)象的時(shí)候,再去加載所需的js。也就是說
復(fù)制代碼 代碼如下:
Using("User"); // 這句話執(zhí)行完畢之后會(huì)創(chuàng)建一個(gè)User對(duì)象,當(dāng)時(shí)僅僅是個(gè)mock
var u = new User(); // 這個(gè)時(shí)候用需要的是真實(shí)的User對(duì)象實(shí)例,就在這個(gè)時(shí)候去動(dòng)態(tài)加載JS文件,并且返回已經(jīng)實(shí)例化的User對(duì)象
大家都知道,異步加載是與當(dāng)前運(yùn)行的狀態(tài)不沖突的,也就是說
復(fù)制代碼 代碼如下:
var u = new User();
這句話執(zhí)行之后,u是一個(gè)沒有實(shí)際意義值的變量,而已。那么,怎么解決這個(gè)問題,我暫且想到的辦法,只能是采用同步策略了。只有當(dāng)js加載完畢,再去執(zhí)行之后的js語句,這個(gè)地方有點(diǎn)遺憾,而且同步可能帶來的瀏覽器假死,也是一個(gè)比較嚴(yán)重的問題,暫且不顧這些問題,希望以后能有更好的辦法解決。
那問題出來了,這么做同步,有什么優(yōu)勢(shì)嗎?
我不知道有什么優(yōu)勢(shì),起碼對(duì)比異步加載,應(yīng)該沒有劣勢(shì)。比如正常的異步加載為
復(fù)制代碼 代碼如下:
$.getScript("user.js",function(){
var u = new User();
});
單單執(zhí)行這個(gè)語句,要執(zhí)行到function,本質(zhì)上也是等user.js加載完畢才會(huì)執(zhí)行,那么對(duì)比
復(fù)制代碼 代碼如下:
var u = new User();
理論上時(shí)間應(yīng)該相當(dāng),因?yàn)槎际堑萿ser.js加載完畢之后才執(zhí)行的。
起碼第二種看起來更像java式的代碼,不必理會(huì)其他非業(yè)務(wù)相關(guān)的代碼。
那么,怎么會(huì)知道需要的對(duì)象在什么地方,怎么加載進(jìn)來?我能想到的就是模擬一個(gè)配置文件,為什么用配置文件,而不是像In.js用add函數(shù)或者其他框架的類似于register的函數(shù),大概我只是想用配置文件,更像java,而且后期的修改起來也會(huì)更解耦一些吧。
復(fù)制代碼 代碼如下:
Using.Config = {
"User" : "/js/user" // 可以隱去.js 因?yàn)榭隙ㄊ羌虞dJS文件了
}
整個(gè)思路大概就是這個(gè)樣子,我在其基礎(chǔ)上進(jìn)行了一些約束,比如加入了命名空間
復(fù)制代碼 代碼如下:
var u = new Using.Modules.User();
這樣可以減少一些全局變量,而且有需要的話,可以插入一些所有對(duì)象可能都具有的共性,減少創(chuàng)建類時(shí)的重復(fù)編碼。
當(dāng)然,也還是支持不使用命名空間的。
為了解決這個(gè)約束的效力,加入了Class.create函數(shù)來進(jìn)行類創(chuàng)建約束。
復(fù)制代碼 代碼如下:
Using.Class.create("User",function(){
}).property({
}).static({
}).namespace(Using.Modules);
這里的大概意思就是
create(類名,構(gòu)造函數(shù))
property(類的屬性)
static(類的靜態(tài)屬性)
namespace(命名空間)
引申到此,為何不加入MVC形式?
后來我發(fā)現(xiàn),要MVC,那么幾個(gè)類之間的動(dòng)態(tài)維護(hù),或者創(chuàng)建之時(shí)就由Using這個(gè)類來自動(dòng)維護(hù),暫時(shí)還沒想到好的解決辦法,所以沒有加入其中,只能自己創(chuàng)建類,自己維護(hù)了.
通過上面的文字,最后得到一個(gè)Using.js
然后在頁面里面就只需要引入一個(gè)
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="using.js"></script>
這樣接下來就可以寫
復(fù)制代碼 代碼如下:
Using("jquery");
Using("User");
$("#ID").click(function(){
var user = new User();
user.name = "xx";
user.show();
});
您可能感興趣的文章:
- JavaScript動(dòng)態(tài)創(chuàng)建link標(biāo)簽到head里的方法
- IE8中使用javascript動(dòng)態(tài)加載CSS的解決方法
- Javascript動(dòng)態(tài)引用CSS文件的2種方法介紹
- javascript中兼容主流瀏覽器的動(dòng)態(tài)生成iframe方法
- javascript動(dòng)態(tài)添加、修改、刪除對(duì)象的屬性與方法詳解
- 深入理解Javascript動(dòng)態(tài)方法調(diào)用與參數(shù)修改的問題
- js加載之使用DOM方法動(dòng)態(tài)加載Javascript文件
- JavaScript 動(dòng)態(tài)創(chuàng)建VML的方法
- javascript動(dòng)態(tài)創(chuàng)建及刪除元素的方法
相關(guān)文章
js調(diào)用activeX獲取u盤序列號(hào)的代碼
js調(diào)用activeX獲取u盤序列號(hào)的代碼,需要的朋友可以參考下。2011-11-11關(guān)于在Servelet中如何獲取當(dāng)前時(shí)間的操作方法
下面小編就為大家?guī)硪黄P(guān)于在Servelet中如何獲取當(dāng)前時(shí)間的操作方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06如何將php數(shù)組或者對(duì)象傳遞給javascript
這篇文章主要介紹了將php數(shù)組或者對(duì)象傳遞給javascript的方法,需要的朋友可以參考下2014-03-03js實(shí)現(xiàn)頁面導(dǎo)航層級(jí)指示效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)頁面導(dǎo)航層級(jí)指示效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08