ESOE-IDE v0.3 技术说明书
Author: Feng WeiGuo (冯卫国)
Email: forxm@21cn.com
Web: http://www.supertree.org
Tel: 86-0755-81030955
All Rights Reserved
2008-9
目录
ESOE-IDE v0.3 技术说明书... 1
1. 设计目标/特性... 3
2.类模型... 3
2.1 类模型和类声明... 3
2.1 类的名称空间管理... 6
3.绑定... 6
3.1 从HTML绑定js类... 6
3.2 从js类绑定DOM元素... 6
4.资源... 7
5.DOM元素寻址... 7
6.事件映射... 8
7.ESOE-IDE加载过程... 9
8. 类文件管理/打包输出/库文件... 9
9.ESOE-IDE对实现DOM类的建议... 10
9.1. 全局Z-index分配... 10
9.2. 事件映射方法... 10
9.3. 控件设计... 10
9.4. 窗体设计... 11
9.5. 对话框设计... 11
附录A. ESOE-IDE工具函数... 13
name convention. 13
$esoe.$preload. 13
$esoe.$declare. 13
$esoe.$new.. 13
$esoe.$derive. 14
$esoe.$import 14
$esoe.$bind. 14
$esoe.$find. 14
$esoe.$init 15
$esoe.$apply. 15
$esoe.$. 15
$esoe.$$. 16
$esoe.$notify. 16
附录B. 资源定义格式... 17
主资源格式... 17
附加资源格式... 17
附录C. 事件映射格式... 18
1. 设计目标/特性
- 1. 由独立的js模块,和独立的html模块构造,减少传统Web设计时两者相互混合;
- 2. 与传统IDE类似,Js和html之间的联系,应是代码(js)和资源(html)之间的关系;
- 3. 伪编译:类库引用完整性检查/打包;
- 4. 制作库文件(Library)功能;
- 5. 事件à方法映射;
- 6. 提供窗口框架/对话框/控件的功能;
- 7. 提供类向导/映射向导等方便编辑;
- 8. 输出的文件的js/html代码压缩;
- 9. 类模型,基于早期版本的ESOE,提供类继承/名称空间等功能;
- 10. 项目文件保存配置;
- 11. 提供js/html语法着色编辑器;
- 12. 自生系统:IDE自身使用js/html编码,使用IDE编译器制作生成;
2.类模型
ESOE-IDE v0.3是从早期版本ESOE v0.2演变而成,去除自动加载/共享/析构等功能,加入重要的类声明概念。
2.1 类模型和类声明
ESOE-IDE使用以下类模型:
- 1.函数(Function)是类的构造函数,用于类实例的初始化;
- 2.每个函数(Function)带有一个声明函数,用于构造类的原型(prototype);
- 3.所有类在使用之前,必须声明,即调用声明函数。
以下给出实现以上类模型的实例,这些实例都可以兼容地应用到实际的编码中。
原始模型:
function MyClass(a,b) //构造函数
{
...
}
MyClass._declare= function() //声明函数
{
MyClass2._declare(); //声明使用的外部类
this.prototype={ //构造原型
p1: 123,
f1: function(c,d)
{
var e= new MyClass2; //使用外部类
}
}
this._declare=function(){} //清除声明函数
}
....
MyClass._declare(); //声明一个类
var o= new MyClass(1,2); //使用这个类
说明:
- 1. 声明函数不带参数,避免引起闭包问题;
- 2. 声明函数结束时清除声明函数,以允许多次声明;
- 3. 使用一个类之前,必须先声明;
- 4. 如果一个类使用了另一个外部类,在类的声明函数开始部分声明此外部类;
- 5. ESOE-IDE中,类的声明函数的默认名称是"_declare";
使用类声明有以下好处:
- 1. 使用大规模类库时,其中不被使用的类可以不用构造原型,加快系统加载,减少资源占用;
- 2. 在类的声明函数开始部分声明外部类,如果此外部类未被加载,可以在应用启动时立即抛出异常,将运行时错误转为设计时错误,利于修改;
混合模型:
function MyClass(a,b) //构造函数
{
}
MyClass._declare= function() //声明函数
{
...
}
$esoe.$preload( "com.MyName.MyClass", MyClass, MyClass._declare ); //载入ESOE名称空间
...
var cls= $esoe.$declare("com.MyName.MyClass"); //声明一个类
var o= new cls(1,2); //使用这个类
说明:
- 1. 使用$esoe.$preload()将类预载入ESOE名称空间,以利于管理;
- 2. 预载入$esoe.$preload()不会调用类的声明函数;
- 3. 使用$esoe.$declare ()声明类;
- 4. $esoe.$declare ()自动清除声明函数;
- 5. 混合模型可用于将已存在的代码快速改造为ESOE-IDE兼容的类;
IDE模型:
$esoe.$preload(
"com.MyName.MyClass", //指定ESOE名称空间
function(a,b) //构造函数
{
},
function() //声明函数
{
...
}
);
说明:
- 1. 调用$esoe.$preload()时,直接使用匿名函数作为参数;
- 2. ESOE-IDE编译器自动检查js代码中以下调用,以确保类引用完整性:
$esoe.$preload
$esoe.$declare
$esoe.$import
$esoe.$new
$esoe.$derive
$esoe.$bind - 3. ESOE-IDE编译器自动检查html代码中的jclass属性,以确保类引用完整性;
2.1 类的名称空间管理
与ESOE v0.2或其它具有名称空间管理框架类似,ESOE-IDE有自已的类名称空间。除了便于管理和避免名称冲突的作用外,ESOE-IDE的类名称空间具有以下特性:
- 1. ESOE-IDE引擎在运行时不会利用类名进行自动加载工作;引用完整性在编译时被处理;
- 2. ESOE-IDE编译器在确保类引用完整性时,按类名提示的路径信息查找对应的类文件;
- 3. 类文件也可以不在对应类库的路径中,文件可以在任意路径位置,只要被加入项目文件中即可;例如可以在引用的类库文件中;
3.绑定
ESOE-IDE使用绑定的方法,将js类和html代码关联。
3.1 从HTML绑定js类
ESOE-IDE引擎将扫描HTML代码,如果DOM元素具有ESOE-IDE专有属性"jclass",则将该DOM元素与指示的js类绑定,生成一个DOM元素的"$jbind"属性,值为js类的一个实例。这种方式称为静态绑定。
例子:
<div jclass="MyClass" οnclick="this.$jbind.MyMethod()">abc</div> <!--简单绑定-->
<div jclass="MyClass{a:1,b:2}"></div> <!--带参数的绑定-->
3.2 从js类绑定DOM元素
ESOE-IDE引擎提供$esoe.$bind函数,动态绑定DOM元素。
例子:
$esoe.$bind(
"MyClass", //js类
ei, //Dom元素
{a:1,b:2} //参数
);
4.资源
ESOE-IDE系统以js代码为主要内容,HTML代码/CSS文件/其它文件作为js代码的附加项,称为附加资源。每一个js类可以带有一个默认的HTML代码,作为绑定DOM元素后设置为DOM元素的innerHTML值,此默认的HTML代码称为主资源。在ESOE-IDE系统中,HTML代码被分割为单独的小块代码而依附于js代码,被称为HTML片段,缩写为HTMI (HTML fragment item)。
例子:
//#ESOE_RES //资源定义头部
this.$res=["",0,"<DIV>abc</DIV>" ]; //主资源
//#HTMI: htmi_MyHtmi2, MyHtmi2.htmi //附加HTMI资源
//#CSS: css_MyCss, MyCss.css //附加CSS资源
//#FILE: file_MyPic_gif, MyPic.gif //附加FILE资源
//#END_ESOE_RES //资源定义结束
说明:
- 1. 每个js类文件只可以有唯一的一段资源定义代码,以"//#ESOE_RES"起头,以"//#END_ESOE_RES"结束;
- 2. 主资源定义在类构造函数的$res属性上;
- 3. 附加资源以固定格式的注释语句定义,由ESOE-IDE编译器处理;
- 4. 附加资源包括3种类型: htmi, css, file
- 5. HTMI附加资源将被ESOE-IDE编译器编码到$esoe.$res数组中统一保存;
5.DOM元素寻址
传统Web程序主要依靠DOM元素的id属性,使用document.getElementById()寻找目标DOM元素。ESOE-IDE系统与传统方法不同,除某些特别场合外,ESOE-IDE主要使用name属性寻找目标元素,以利于js类对HTMI的封装和重用。
例子:
<div id=from>
<div>
<div name=name1></div>
<div name=name2>
<div name=name3></div>
</div>
</div>
</dv>
...
e= document.getElementById(‘from'); //获取起始DOM元素
ei= $esoe.$find( "name1", e); //寻找DOM子元素
ei= $esoe.$find( "name2.name3", e); //寻找多级DOM子元素
ei= $esoe.$find( "name3", e); //错误的寻址方式,无法找到元素
说明:
- 1. 单个name寻址查找所有子孙节点的name属性,匹配第一个符合的节点;
- 2. 单个name寻址不必是直接子节点;
- 3. 匹配单个name属性的节点的所有祖先节点,到起始DOM元素为止,都不出现name属性;
- 4. 多级name寻址使用"."联接;
6.事件映射
与DOM元素绑定的js类,可以建立事件映射表,ESOE-IDE引擎自动将元素事件与js类方法进行关联。
例子:
//#ESOE_MAP //事件映射定义头部
this.$map=[
["","click","OnClickMain" ], //映射主DOM元素事件
["name2.name3","click","OnClickName3" ] //映射子DOM元素事件
];
//#END_ESOE_MAP //事件映射定义结束
说明:
- 1. 每个js类文件只可以有唯一的一段事件映射定义代码,以"//# ESOE_MAP"起头,以"//# END_ESOE_MAP"结束;
- 2. 事件映射定义在类构造函数的$map属性上;
- 3. 事件映射机制可以映射以静态绑定方法加载的直接位于HTMI中的DOM元素的事件,称为静态映射;
- 4. 事件映射机制可以映射在构造函数中创建的DOM元素的事件,或在构造函数中以动态绑定方法加载的DOM元素的事件,称为动态映射;动态映射可能会降低系统的加载速度;
7.ESOE-IDE加载过程
如果Web应用为<body>指定了绑定的js类,那么ESOE-IDE引擎加载时实现以下过程:
- 1. 在window.onload调用$esoe.$bind绑定<body>和指定的入口类;
- 2. 通过分析HTML/HTMI的jclass属性,自顶(<body>)向底加载类的主资源(将主资源HTMI设置为innerHTML);
- 3. 自底向顶(<body>)创建js类实例,将实例保存为关联DOM元素的$jbind属性;
- 4. 创建js类实例的同时进行事件映射;
说明:
- 1. 当创建一个绑定于DOM元素的js类实例时,在调用其构造函数之前,对应的DOM元素的所有子孙元素已完成了加载主资源的工作,并且所有子孙元素已完成绑定,具有相应的$jbind属性;
- 2. 当创建一个绑定于DOM元素的js类实例时,在调用其构造函数之前,对应的DOM元素的所有祖先元素未完全加载主资源,并且没有绑定;
8. 类文件管理/打包输出/库文件
ESOE-IDE按以下方法对类文件进行管理和输出:
- 1. 每个ESOE类的源代码应完整地放在单独的*.js文件中;
- 2. js类用到的CSS文件以单独的*.css文件保存,并以附加CSS资源的方式记录在js类中;
- 3. js类用到的外部文件,如图片等,以单独的文件保存,并以附加FILE资源的方式记录在js类中;
- 4. 如果js类用到多个独立的HTMI资源,文件以单独的*.htmi文件保存,并以附加HTMI资源的方式记录在js类中;
- 5. ESOE-IDE编译器对每个文件的打包方式包括:
pack方式:将文件打包至输出文件,所有js文件打包到最终的htm或js输出文件,所有的css打包到最终的htm或css输出文件,所有的FILE资源拷贝到输出目录;
pack_cp方式:(暂未实现)与pack方式类似,将js文件或css文件的顶部版权说明(第一个块注释)集合放置到最终的htm或js或css输出文件的顶部;
link方式:将文件链接到输出文件,如js文件以"<script src=...>"的方式联接,css文件以"<link ...>" 的方式联接;
default方式:见下; - 6. ESOE-IDE编译器支持2种编译模式:Debug模式和Release模式,可分别设置不同的输出目录;2种编译模式有以下区别:
Debug模式:如果文件设置为default方式,则默认为link方式打包;
Release模式:如果文件设置为default方式,则默认为pack方式打包; - 7. ESOE-IDE编译器支持2种输出模式:
App输出:所有内容输出至主htm文件,此htm文件可作为一个独立的Web应用运行于浏览器;如果设置了输出lib.js文件,则所有pack方式js文件打包至lib.js文件,并在主htm文件链接;如果设置了输出lib.css文件,则所有pack方式css文件打包至lib.css文件,并在主htm文件链接;
Lib输出:如果没有设置主htm文件,则仅输出lib.js文件和lib.css文件,与App输出类似,但没有htm作为Web应用入口,只可被其它项目引用;
9.ESOE-IDE对实现DOM类的建议
本节提出一些设计方法和原则,这些方法是在ESOE-IDE建立自身的过程中总结出来并遵守的,建议用户使用。
9.1. 全局Z-index分配
resizer: 100->110(dragging)
popup menu: 105
dragger: 110
Window Manager: 1000 -> *
_modal: 100000
9.2. 事件映射方法
MyMethod: function( evt, e )
{
if(!e) e= this.FindMeFromEvent(evt);
...
}
说明:
- 1. 加入第2参数e的作用是,使事件映射函数除了处理系统事件外,还可以被代码直接调用,例如 MyMethod( null, e ).
- 2. FindMeFromEvent实现从事件对象查找主DOM元素,可以从org.supertree.dom.Base继承,或直接拷贝代码实现。
FindMeFromEvent: function( evt )
{
return $esoe.$find(this,evt.srcElement?evt.srcElement:evt.target);
}
9.3. 控件设计
- 1. 控件可从org.supertree.dom.Base继承;
- 2. 可以利用ESOE自定义事件$notify机制;
9.4. 窗体设计
- 1. 窗体从org.supertree.dom.Window.Window继承;
- 2. 窗体可以加载菜单/工具栏等;
- 3. 窗体有可重载OnCommand()方法,用于处理菜单/工具栏命令;
9.5. 对话框设计
由于当前2种流行浏览器ie6/firefox对于实现对话框有诸多不一致和不必要的权限设置,ESOE-IDE自行实现异步式对话框,以解决一些设计上的不便。
- 1. 将对话框划分为运行前和运行后2个方法进行处理;运行前方法用于打开对话框,运行后方法用于处理关闭对话框后的数据处理;
- 2. 对话框从org.supertree.dom.Window.Dialog继承;
- 3. 对话框是全局DOM对象,具有唯一的id属性;通常只建一次,后续调用将重新使用已建立的DOM对象;
- 4. 对话框有可重载InitModal()方法,用于初始化对话框;
- 5. 对话框不可重入,即不可在一个对话框打开时,打开另一个由相同js类创建的对话框;可重入对话框应另行设计;
由ESOE-IDE类向导生成的对话框可用以下代码打开:
$esoe.$import("MyDialog").prototype.DoGlobalModal(
e, //主DOM元素对象
"$jbind.OnMyMethod", //回调函数名称引用字串
p //参数
);
对话框数据处理回调函数使用以下形式:
OnMyMethod: function(e,cmd,pOut)
{
if(cmd=="ok")
{
...
}
}
说明:
- 1. 回调函数的第1参数(e)为调用DoGlobalModal时传入的第1参数;
- 2. 回调函数的第2参数(cmd)为对话框类向ExitModal传入的第2参数,通常为点击按钮的name属性;
- 3. 回调函数的第2参数(pOut) 为对话框类向ExitModal传入的第3参数,为输出数据对象;数据名称通常与主资源DOM元素的name属性对应;
附录A. ESOE-IDE工具函数
附录B. 资源定义格式
附录C. 事件映射格式
function.$map= [ mi1, mi2, ... ];
mi: map item mi= [ "dom_ns", "event_name", "method_name", "bDynamic" ];
dom_ns: dom element "name" attribute list, items are separated by ".". "" means the e itself; or directly a dom object.
event_name: event name without "on" prefix, such as "click"; or esoe self-defined notify event "$notify".
method_name: class method name, the event method is like: function(evt){...}.
bDynamic: dynamic mapping, optional, can be "1"( must be string); if fail to find static element, $esoe.$bind will using $esoe.$find() to search the dynamic element, which may slow down the binding process. |