技术文章
本篇梳理 O2OA 平台表单设计器中的事件体系及其脚本写法。事件分为元素事件与组件事件,前者基于封装后的页面节点,回调与浏览器原生事件同名;后者依附组件对象,可在加载前后或保存前触发脚本。文中说明事件上下文对象指向脚本运行环境,并给出获取当前组件的通用写法,以及用脚本绑定、批量绑定与主动触发事件的方法。末尾列出自表单与组件加载各阶段的事件,并提醒延迟加载的容器激活后才执行内部事件。
设计表单时经常会有这样的需求:在表单或者组件加载前/加载后执行脚本,以改变表单或组件的样式和行为。或者在用户点击组件时执行脚本。表单的事件正是为这类场景而设计的。
表单中的事件分为两类:组件事件和 Element 事件。
打开表单设计器后,在表单属性或组件属性的“事件”附签中可以看到一组事件,这组事件包含了这两种事件。表单事件见下图。
开发人员可以在事件编辑器中编写脚本,也可以添加或删除事件。
添加的组件事件需要在 API 的列表中才有效。
Element 是经 Mootools 框架封装后的 HTML DOM 对象。
Element 的事件类型与 HTML DOM 对象一致,如"focus、click、blur";等。
本平台的 Element 事件是基于 Mootools 的 Element.Event 类封装的。
表单设计器中的事件,this 对象指向平台的 MWF.xScript.Environment 对象,这是平台脚本的上下文,可以执行类似于"this.form";的脚本。
平台在每次运行事件的时候,都会为 this 对象添加一个属性"target";。我们可以通过 this.target 来获取当前组件。
//获取当前组件对象
this.target;
//等价于
this.form.get("fieldName");在表单设计器的各种组件中添加事件后,表单加载时平台会把事件添加到相应的 Element 对象。下表列出了各种组件对应的 Element 事件对象。
组件类型 | Element 事件对象 | 获取 Element 脚本 |
Checkbox 多选按钮 | input[type='checkbox'] | this.form.get("fieldName").node.getElements("input['type='checkbox']") |
Radio 单选按钮 | input[type='radio'] | this.form.get("fieldName").node.getElements("input['type='radio']") |
Textarea 多行文本 | textarea | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Textfield 单行文本 | input | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Org 人员 | 第一个子 div | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Calendar 日期 | input | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Combox 组合框 | 第一个子 div | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Opinion 意见框 | 第一个子对象 | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Address 地址选择 | 第一个子对象 | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
Number 数字 | input | this.form.get("fieldName").node.getFirst() || this.form.get("fieldName").node; |
其他 | node | this.form.get("fieldName").node; |
样例:
在标识为"subject";的文本组件的 focus 事件中已添加脚本。
对于上面的脚本,在光标进入输入框的时候执行。
如果希望由其他条件来触发这个事件,也可以通过下面的脚本来执行:
var node = this.form.get("subject").node; //获取组件节点
( node.getFirst() || node ).fireEvent("focus"); //触发focus事件在上面的例子中,我们都是通过组件属性中的事件区域来添加事件。除了这种方法,还可以在脚本中增加事件。
myElement.addEvent(type, fn);
参数:
type - (string) 事件名,没有'on';。
fn - (function) 事件函数。
返回:
(element)当前元素。
样例:
以下脚本可实现上一个样例的功能,在一个标识为"subject";的文本组件的 focus 事件中增加脚本
var node = this.form.get("subject").node;
node.getElement("input").addEvent("focus", function(ev){
//ev 是Mootools Element的Event对象
//这里的this指向input
this.setStyle("border","1px solid blue");
})myElement.addEvents(events);
参数:
events - (object) 包含多个事件的对象(对象的 key 为事件名,value 为事件函数)。
返回:
(element)当前元素。
样例:
var node = this.form.get("subject").node;
node.getElement("input").addEvents({
"focus" : function(ev){
//ev 是Mootools Element的Event对象
//这里的this指向input
this.setStyle("border","1px solid blue");
},
"blur": function(ev){
//ev 是Mootools Element的Event对象
//这里的this指向input
this.setStyle("border","1px solid gray");
}
})myElement.fireEvent(type[, args[, delay]]);
参数:
type - (string) 事件名称(例如"click" )
args - (mixed, optional) 事件函数的参数,数组或单个对象,如果超过一个参数,必须是一个数组。
delay - (number, optional) 延迟(ms)执行时间。
返回:
(element)当前元素。
样例:
var node = this.form.get("subject").node; //获取组件节点
( node.getFirst() || node ).fireEvent("focus"); //触发focus事件平台中的组件是一组基于 Mootools Class 生成的对象。Mootools Class 是 MooTools 框架的基类。
Mootools Class 中有一系列特性,其中包括 Class:Event。
在表单设计器的各种组件中添加事件脚本后,表单加载时代码运行到相应位置,这些脚本就会被触发。例如平台在加载组件(包括生成 Html Dom、赋值等)之前执行 queryLoad 事件中的脚本,加载组件之后执行 postLoad 中的事件。
表单设计器中的事件,this 对象指向平台的 MWF.xScript.Environment 对象,这是平台脚本的上下文,可以执行类似于"this.form";的脚本。
平台在每次运行事件的时候,都会为 this 对象添加一个属性"target";。我们可以通过 this.target 来获取当前组件。
//获取当前组件对象
this.target;
//等价于
this.form.get("fieldName");某些需要参数的事件,平台在每次运行时会为 this 对象添加属性"event ";,我们可以通过 this.event 获取参数。
//有时候可以通过this.event获取参数 this.event;
系统在加载组件时,会根据 json 的 isReadonly 判断生成输入框还是 div 节点。
如果希望由其他条件来触发这个事件,也可以通过下面的脚本来执行:
var field = this.form.get("subject"); //获取组件
field.fireEvent("queryLoad"); //触发queryLoad事件在上面的例子中,我们都是通过组件属性中的事件区域来添加事件。除了这种方法,还可以在脚本中增加事件。
myClass.addEvent(type, fn[, internal]);
参数:
type - (string)事件的类型(例如'queryLoad'),包含在表单设计器里组件的事件。
fn - (function)事件函数。
internal - (boolean, optional)设置函数属性:internal 为 true。internal 属性通常用来防止删除。
返回:
(object)这个类的实例。
样例:
在表单保存时添加一个事件,将临时字段置空。
var form = this.form.getApp().appForm; //获取表单组件
form.addEvent("beforeSave", function(){ //添加保存前事件
this.form.get("tmpField").setData(''); //给临时字段置空
}.bind(this)) //通过 bind(this), 把上下文传到事件方法里myClass.addEvents(events);
参数:
events - (object)一个 key:value 对象,key 事件名称(如"queryLoad" ),和值,当事件发生时要调用的函数。
返回:
(object)这个类的实例。
注: 通过这种方式添加事件,this.target 和 this.event 均为空。
样例:
var form = this.form.getApp().appForm; //获取表单组件;
form.addEvents({
"beforeSave" : function(){ //添加保存前事件
this.form.get("tmpField").setData(''); //给临时字段置空
}.bind(this), //
"beforeDelete": function(){ //增加删除前事件
//do something
}
})myClass.fireEvent(type[, args[, delay]]);
参数:
type - (string)事件的类型(例如'beforeSave')。
args - (mixed,optional)传递给函数的参数。要传递多个参数,该参数必须是一个数组。
delay - ( number,optional)等待时间,单位毫秒。
返回:
(object)这个类的实例。
样例一:
var form = this.form.getApp().appForm; //获取表单组件;
form.fireEvent("beforeSave"); //触发beforeSave事件样例二:如果临时字段由触发时传入,可以这样写
var form = this.form.getApp().appForm; //获取表单组件;
form.fireEvent("beforeSave",["tmpFieldName1"]); //触发beforeSave事件则添加的事件需要改成如下:
var form = this.form.getApp().appForm; //获取表单组件
form.addEvent("beforeSave", function( fieldName ){ //添加保存前事件
this.form.get(fieldName").setData(''); //给临时字段置空
}.bind(this)) //通过 bind(this), 把上下文传到事件方法里a、执行主表单事件 queryLoad -> beforeLoad -> beforeModulesLoad;
b、根据组件在主表单的位置从上到下,从里到外执行组件的 queryLoad->postLoad->load 事件;
c、执行主表单事件 postLoad;
d、子表单、子页面、部件上的直接事件不会被执行,但子表单里组件的事件也按规则 b 执行;
e、由于子表单、子页面、部件是异步加载,这些组件内的组件事件在异步加载完成后分别执行;
f、执行主表单事件 afterModulesLoad -> afterLoad;
g、当 Tab 组件、子表单、公文管理器等组件被设置为延迟加载时,主表单加载时这些组件内的子组件不会加载。当这些组件被激活时,按规则 b 执行事件。
表单的直接事件 | 说明 |
queryLoad | 表单加载前触发。数据(businessData)、预加载脚本和表单 html 已经就位。 |
beforeLoad | 表单加载前触发。已提示抢办锁定。 |
beforeModulesLoad | 表单的所有组件加载前触发,此时表单的样式和 js head 已经加载。 |
postLoad | 表单加载后触发。主表单的组件加载完成,但不保证子表单、子页面、部件加载完成。 |
afterModulesLoad | 表单的所有组件加载后触发。表单包含有子表单、子页面、部件时,此事件会在这些组件加载后触发。 |
afterLoad | 表单加载后触发。表单包含有子表单、子页面、部件时,此事件会在这些组件加载后触发。 |
相关内容