JavaScript Integration 体验教材
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 >
….
<!-- 加入引导脚本 -->
< 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);
}
}
* 滑动面板实现.
* 当指定元素可见时,将其第一个子元素向上滑动至完全被遮掩(折叠)。
* 当指定元素不可见时,将其第一个子元素向下滑动至完全显示(展开)。
*/
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 );
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 >
< 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 >
< 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文件,那是类库开发者做的事.
* 类库开发者
在此框架下开发出方便实用的脚本库,您需要编写一些通用脚本,同时设置脚本依赖,做到任何类/函数,导入即可运行。