JSI是一個簡單、無侵入(被管理的腳本無需考慮JSI的存在)的腳本管理框架, JSI的出現,可以做到如下幾點:

* 按需裝載。
* 管理依賴,避免依賴的保露、擴散,提高類庫的易用性。
* 執行環境的隔離,避免名稱沖突。

類庫裝載

    動態裝載類庫是按需裝載的基礎,JSI的裝載方式有三種:即時同步裝載(可能阻塞)、延遲同步裝載(需要編譯)、異步裝載。這里先演示一下最簡單的方式,即時同步導入:

示例:重寫一下jQuery的hello world。
….
<!-- 加入引導腳本 -->
<script src="../scripts/boot.js"></script>
….
<script>
//導入jQuery的$函數
$import("org.jquery.$");
//使用jQuery的$函數
$(document).ready(function(){
  alert(
"Hello World");
 });
</script>
….

    這是默認的導入方式,當能,如果網絡環境不好,這可能產生阻塞問題。所以JSI2開始增加了仍外兩種導入模式。延遲同步導入,異步導入。具體用法請查看文章后面的導入函數參考。

依賴管理

    Java可以隨意的使用第三方類庫,可是JavaScript卻沒那么幸運,隨著類庫的豐富,煩雜的依賴關系和可能的命名沖突將使得類庫的發展越來越困難。程序的易用性也將大打折扣。

    命名沖突的危險無形的增加你大腦的負擔;隨著使用的類庫的增加,暴露的依賴也將隨之增加,這是復雜度陡增的極大禍根,將使得系統越來越復雜,越來越難以控制。潛在的問題越來越多,防不勝防。

    所以,我們建議類庫的開發者將自己類庫的依賴終結在自己手中,避免依賴擴散,以提高類庫的易用性。

    為了演示一下JSI的依賴管理,我們編寫一個復雜一點的類庫:類似Windows XP文件瀏覽器左側的滑動折疊面板(任務菜單)效果。

1.編寫我們的折疊面板函數(org/xidea/example/display/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);
  }
}

2.編寫包定義腳本,申明其內容及依賴(org/xidea/example/display/__$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);
//給effect.js腳本添加對net.conio.prototype包中$函數的裝載后依賴this.addScriptObjectDependence("effect.js",
"net.conio.prototype.$",false);

3.HTML代碼:
<html>
  
<head> 
  
<title>重用aculo Effect腳本實例</title>
  
<link rel="stylesheet" type="text/css" href="/styles/default.css" />
  
<script src="/scripts/boot.js"></script>
  
<script>
    $import(
"org.xidea.display.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的具體實現去實現我們需要的滑動折疊功能。

    這個效果只是八行代碼,比較簡單,但是它用到了Scriptaculous Effect類庫,Scriptaculous Effect又簡接用到了Prototype類庫,所以,傳統方式使用起來還是比較復雜,有一堆腳本需要導入prototype.js,effects.js,builder.js,更加痛苦的是這些腳本的導入還要遵守一定的順序。

    但是,如果我們使用JSI 明確申明了這些依賴,那么使用起來就簡單多了,只一個import就可以完全搞定。
    此外 這里還有一個額外的好處,我們類庫中依賴的那些腳本,并不會對外部保露,在頁面上是不可見的,也就是說,這些依賴完全終結在剛才編寫的類庫中,不必擔心使用這些類庫帶來的名稱污染問題。


環境隔離

    眾所周知, Scriptaculous所依賴的Prototype庫與jQuery存在沖突。所以同時使用比較困難。
    下面的例子,我們將在同一個頁面上同時使用Scriptaculous和 jQuery 類庫。示范一下JSI隔離沖突功能。
示例頁面(hello-jquery-aculo.html):
<html>
<head>
<title>Hello jQuery And Scriptaculous</title>
<!-- 加入引導腳本 -->
<script src="../scripts/boot.js"></script>
<script>
//導入jQuery
$import("org.jquery.$");
//導入Scriptaculous
$import("us.aculo.script.Effect");

$(document).ready(
function(){
  
//使用jQuery添加一段問候語
  $("<p id='helloBox' style='background:#0F0;text-align:center;font-size:40px;cursor:pointer;'>\
Hello jQuery And Scriptaculous</p>
")
    .appendTo('body');
  $('#helloBox').ready(
function(){
    
//使用Scriptaculous高亮顯示一下剛才添加的內容
    new Effect.Highlight('helloBox');
  }).click(
function(){
    
//當用戶單擊該內容后使用jQuery實現漸出
    $('#helloBox').fadeOut();
  });
 });
</script>
</head>
<body>
<p>文檔裝載后,jQuery將在后面添加一段問候語;并使用Scriptaculous高亮顯示(Highlight);在鼠標點擊后在使用jQuery漸出(fadeOut)。</p>
</body>
</html>




其他話題

    JSI組件模型:
    頁面裝飾引擎:用于裝飾樸素html元素的框架,實現零腳本代碼的web富客戶端編程,更多細節請訪問jsi官方網站。


參考:

    腳本導入函數
    腳本導入函數是JSI唯一的一個在頁面上使用的系統函數。

  function $import(path, callbackOrLazyLoad, target )
      path 類庫路徑
      callbackOrLazyLoad 可選參數,如果其值為函數,表示異步導入模式;如果其值為真,表示延遲同步導入模式,否則為即時同步導入(默認如此)。
      Target 可選參數(默認為全局變量,所以說,這種情況等價于直接聲明的全局變量),指定導入容器。
名詞解釋:
    * 自由腳本
通過<script>標記引入或直接編寫的腳本,我們不建議在使用JSIntegration之后,仍舊使用script src導入JSI啟動腳本(boot.js)之外的腳本。
    * 托管腳本
通過$import函數直接或間接加載的腳本。這些腳本將在一個獨立的執行上下文裝載,不會污染全局環境。
    * 腳本依賴
若要使用A,需要導入B,則A依賴B。
A、B可以是腳本文件,也可以是腳本文件中的某個腳本元素。
    * 類庫使用者
類庫的使用者,您只需再頁面上書寫腳本,導入類庫,編寫自己的簡單腳本,一般情況請不要編寫js文件,那是類庫開發者做的事.
    * 類庫開發者
在此框架下開發出方便實用的腳本庫,您需要編寫一些通用腳本,同時設置腳本依賴,做到任何類/函數,導入即可運行。