在上一章中,我们了解了在ShineWay下开发所得到的第一个初始化的页面。我们以一个简单的加法运算为例子,把它命名为SimpleAdd,分析这样的例子我们很快知道,需要两个输入数,和一个输出数。以及一个按钮来触发计算,因此我们的我们编写一个控制器:
namespace ShineWay.AjaxControl.Sample
{
/// <summary>
/// Calculator 的摘要说明。
/// </summary>
public class SimpleAdd:BaseControl
{
private AjaxTextBox add1;
private AjaxTextBox add2;
private AjaxTextBox result;
private AjaxButton addClick;
/// <summary>
/// 初始化当前控制其中的组件
/// 并且设置界面各个控件初始值
/// </summary>
public override void InitView()
{
this.add1 = new AjaxTextBox();
this.AddComponent(this.add1);
this.add2 = new AjaxTextBox();
this.AddComponent(this.add2);
this.result = new AjaxTextBox();
this.AddComponent(this.result);
this.addClick = new AjaxButton();
this.addClick.Value = "Add";
this.addClick.OnClick += new ClickEventHandler(addClick_OnClick);
this.AddComponent(this.addClick);
}
/// <summary>
/// Add Button Click
/// </summary>
/// <param name="com"></param>
void addClick_OnClick(IComponent com)
{
this.result.Value = System.Convert.ToInt32(this.add1.Value)+System.Convert.ToInt32(this.add2.Value);
}
}
}
对,我们要写的代码就这么多,根据我们前一章所讲,初始界面生成引擎会产生如下HTML代码的页面:
<html>
<head>
<title>AjaxCRM</title>
<script src="../Core/lib.js"></script>
<link href="../Style/bugs.css" type="text/css" rel="stylesheet">
</head>
<body>
<form id='default' action='ShineWay.AjaxControl.Sample.SimpleAdd' method='post'>
<fieldset><input type="text" id="default_0" value="" ><br>
<input type="text" id="default_1" value="" ><br><input type="text" id="default_2" value="" ><br>
<input type="button" id="default_3" value="Add" οnclick="CallAjax();" ><br>
</fieldset>
</form>
<br>
</body>
</html>
它会在有事件绑定的按钮Add的onclick中加上οnclick="CallAjax();"的语句,使得我们在按下此button时,浏览器调用了CallAjax()函数,因为系统会生成对lib.js的引用语句,因此我们查找lib.js能够知道CallAjax是如何完成交互的:
function CallAjax(){
var req = new Request();
if(CallAjax.arguments.length == 3){
req._eventName=CallAjax.arguments[0];
req._eventSource=CallAjax.arguments[1];
var com = document.getElementById(req._eventSource);
while(com){
if(com.tagName.toLowerCase() == "form"){
req._form = com;
req._control = com.action;
break;
}
com = com.parentElement;
}
if(!CallAjax.arguments[2]) req._values=' ';
AjaxClient.DoMethod(DealWithResult,req.getXml());
}else{
AjaxClient.DoMethod(DealWithResult,req.getXml());
}
}
根据这段代码,我们能够察觉到发起Ajax请求的的数据完全来自于Request这个对象的getXml方法,它生成了请求的XML参数,并发给后台Facade网关.CallAjax则可以根据参数的差异来改善同步调用抑或异步调用等多样化的调整。在请求信息中比较重要的参数是eventSource和eventName他们就是此次请求发起的原因。可以让后台处理准确地定位到事件钩子函数从而实现事件处理。
因此我们看一看requet.getXml的写法(完整的信息请参阅文件中的源码)
if(this._control=="") this.setEvent();
if(this._values=="") this.setValues();
var xml = "<request>";
xml += "<form>"+this._form.id+"</form>";
xml += "<control>"+this._control+"</control>";
xml += "<event>"+this._eventName+"</event>";
xml += "<source>"+this._eventSource+"</source>";
xml += "<values>"+this._values+"</values>";
xml += "</request>";
return xml;
我们可以总结一下请求XML信息中的重要元素:表格ID,控制器名称,事件名称,事件源,参与事件的参数值。
我们知道这样一段Request的XML请求文档发送到后台网关,现在让我们把视角转换到后台上去。
首先接受到此段XML的是AjaxPage类,我们称他为网关.它接收到这段请求XML后要做的工作如下:
1.使用类RequestXML解析XML文档。
2.从缓存中得到或重新建立控制器对象control.
3.根据控件ID把传输过来的当前数据值设置到控件的值域中去.
4.根据事件源和事件名称调用相关控件的绑定的事件处理程序.
5.获取事件处理程序之后发生变化的控件数据和属性数据,样式数据等,并封装成ResponseXML返回。
详细代码请参越AjaxComm包下的AjaxPage网关类。
现在ResponseXML数据包回到了前台,交给了我们前面看到的JS函数DealWithResult.而他正好对应调用的是Response对象的apply函数来应用相应的结果.详细代码请参阅core/response.js
他根据ID逐个设置response中提到的控件的值,属性或样式。
ShineWay提倡所有的样式都用样式文件定义class的方式指定,这样有利于我们样式的处理和值,属性的处理有一个共同的方式。
这一章主要讲事件的触发以及事件处理过程的原理,这是本框架的核心思想。
从下一章可以在各个细节处展开讨论一些相关的处理技术。