Java的成功,離不開它那個龐大的類庫,不單是sun的類庫,很多細節的實現都取自第三方(如xml解析采用Apache的實現)。
JSI暫時不算公共API,但是我們可以集成其他成熟的類庫,同時隔離他們的依賴,隔離各個腳本的執行上下文,消除命名沖突的危險。
這裡我們詳細介紹一個復雜一點的實例:類似Windows XP文件浏覽器左側的滑動折疊面板(任務菜單)效果。
我們先集成Scriptaculous Effect類庫,並且在這個基礎上對一個面板折疊效果做一個簡單的封裝,展示框架的類庫封裝功能。
1。集成Scriptaculous類庫:
這裡我們不做過多介紹,詳細情況請參考集成實戰;我們發布的版本中已經把Scriptaculous放置於us.aculo.script包中,您可以把這些作為系統內置的類庫使用。
2。編寫我們的折疊面板函數(example/effect.js):
/**
* 滑動面板實現.
* 當指定元素可見時,將其第一個子元素向上滑動至完全被遮掩(折疊)。
* 當指定元素不可見時,將其第一個子元素向下滑動至完全顯示(展開)。
*/
function slidePanel(panel){
panel = $(panel);
if(panel.style.display=='none'){
//調用Scriptaculous Effect的具體滑動展開實現
new Effect.SlideDown(panel);
}else{
//調用Scriptaculous Effect的具體滑動閉合實現
new Effect.SlideUp(panel);
}
}
3。編寫包定義腳本(example/__$package.js):
添加slidePanel(滑動面板控制)函數
this.addScript("effect.js","slidePanel",null);
給effect.js腳本添加對us.aculo.script包中effects.js腳本的裝載後依賴this.addScriptDependence("effect.js", "us/aculo/script/effects.js",false);
4。在網頁上運用上面的類庫:
<html>
<head>
<title>重用aculo Effect腳本實例</title>
<link rel="stylesheet" type="text/css" href="/styles/default.css" />
<script src="/scripts/boot.js"></script>
<script>
$import("example.slidePanel");
</script>
</head>
<body>
<div class="menu_header"
onclick="slidePanel('menu_block1')">
面板 1
</div>
<div class="menu_block" id="menu_block1">
<ul>
<li>text1</li>
<li>text2</li>
<li>text3</li>
</ul>
</div>
</body>
</html>
onclick="slidePanel('menu_block1')"這個事件函數將在我們點擊面板標題時觸發,然後會調用Scriptaculous Effect去實現我們需要的滑動折疊功能。
java可以隨意的使用第三方類庫,可是JavaScript卻沒那麼幸運,隨著類庫的豐富,煩雜的依賴關系和可能的命名沖突將使得類庫的發展越來越困難。程序的易用性也將大打折扣。
命名沖突的危險無形的增加你大腦的負擔;隨著使用的類庫的增加,暴露的依賴也將隨之增加,這是復雜度陡增的極大禍根,將使得系統越來越復雜,越來越難以控制。潛在的問題越來越多,防不勝防。
JSI的出現,可以解決上述問題,我們建議類庫的開發者將自己類庫的依賴終結在自己手中,避免依賴擴散,以提高類庫的易用性。
同樣使用上面的例子,假如我們想拋開JSI,實現同樣的功能,那我們的頁面代碼將是(類庫代碼不用改動):
<html>
<head>
<title>重用aculo Effect腳本實例</title>
<link rel="stylesheet" type="text/css" href="/styles/default.css" />
<!--
<script src="/scripts/boot.js"></s cript>
<script>
$import("example.slidePanel");
</sc ript>
-->
<script src="/scripts/net/conio/prototype/v1_5/prototype.js">
</script>
<script src="/scripts/us/aculo/script/v1_7/effects.js">
</script>
<script src="/scripts/us/aculo/script/v1_7/builder.js">
</script>
<script src="/scripts/example/effect.js">
</script>
</head>
<body>
<div class="menu_header"
onclick="slidePanel('menu_block1')">
面板 1
</div>
<div class="menu_block" id="menu_block1">
<ul>
<li>text1</li>
<li>text2</li>
<li>text3</li>
</ul>
</div>
</body>
</html>
這個例子的html代碼明顯比上面的復雜了,一堆堆的script標簽,而且還是有序的;還出現在頁面上,重構起來也極其麻煩。
可以看出,JSI的加入可以讓類庫更加易用,html代碼更為簡潔,最終用戶已經不必關心所用類庫的依賴了。
JSI中每一個腳本有一個單獨的執行上下文。各個腳本頂部變量你可以隨便使用,不必擔心不同腳本中的命名沖突,不會污染全局變量空間,這種方式可以用於解決某些類庫間變量沖突的問題(如jQuery和Prototype的$函數)。我們甚至可以做到同一個頁面上間接加載同一種類庫的兩個不同版本,不相互影響。
使用JSI後,很多細節我們可以在包中封裝掉,不需要告訴類庫使用者太多。大大增加類庫的易用性。同時,類庫封裝的支持可以讓我們在第三方庫的基礎上輕松的按自己的喜好編寫自己的類庫,同時避免依賴擴散造成的復雜度增加。
使用JSIntegration唯一多出的負擔就是編寫包定義文件,不過想想這種定義文件可是一勞永逸的(以後就不需要每次導入腳本的時候都小心翼翼的判斷那個腳本先導入那個後導入,有那些間接使用到的類庫需要導入,等等),而且有了包結構後對於代碼組織、重用,以及文檔的編寫閱讀,都將非常有利。