深刻理解EXT与服务器端的交互

EXT是一款强大的AJAX框架,其UI设计非常华丽,所以在对UI要求高的项目中可以使用!
前面一段时间发了一篇封装的EXT CRUD面板,地址为http://www.phpchina.com/bbs/thread-59552-1-1.html
只是单纯的贴出了代码,对于其中的运行原理并未提及到,这篇文章将分享该CRUD面板实现原理,好了,不废话,正式开始。
下面的内容是毕业论文中的一部分,所以大家看看就是

EXT做为与用户交互的前端,其功能可以概括为:生成用户界面,与用户实现交互,并与程序(PHP,.NET等)后台通信来完成与用户的交互。下面就这几个功能的实现原理做介绍。
[b]1.1生成用户界面[/b]

EXT别广泛接受认可的原因之一便是他拥有良好的用户外观。

一个系统中最主要的功能便是实现CRUD(新增,读取,更新,删除),同时还有查询。为了将这些功能集中在一起,特意封装了一个EXT的CRUD面板,将这些常用的功能封装成一个类,以便创建易用性良好的界面。该CRUD类的程序代码见前面的文章。
CRUD面板是从EXT的panel继承来的

/**
* 定义命名空间
*/
Ext.namespace("Mis.Ext");
/*
*CRUD面板基类
*/
//继承EXT的Panel,创建CRUD面板
Mis.Ext.CrudPanel=Ext.extend(Ext.Panel,{……});
//限于篇幅就不列出全部代码
//EXT里的继承用的是Ext.extend(组件名,{实现代码});
//要使用这个CRUD面板,需要继承实现它,我们举一个例子
//继承CrudPanel,创建污水厂管理面板
AddPlantPanel=Ext.extend(Mis.Ext.CrudPanel,{
id:"AddPlantPanel",//id号是表示一个面板的唯一标志
title:"污水厂管理",//面板的名称,见上图
baseUrl:"Plant.aspx",//数据源地址
//根据实际需要,重载编辑方法
edit:function(){
CommentPanel.superclass.edit.call(this);//调用基类方法
var record=this.grid.getSelectionModel().getSelected();
if(record){
var id=record.get("plantID");
this.fp.form.setValues({ID:id});
}
},
save:function(){//保存
var id=this.fp.form.findField("ID").getValue();
this.fp.form.submit({
waitMsg:'正在保存。。。',
url:this.baseUrl+"?cmd="+(id?"Update":"Save"),
method:'POST',
success:function(form_instance_create, action) {
Ext.MessageBox.alert('友情提示', action.result.info);
},
failure:function(form_instance_create1, action1){
Ext.MessageBox.alert('友情提示', action1.result.info);
},
scope:this
});
},
removeData:function(){//删除
this.remove('plantID');
} ,
createForm:function(){//创建新建和修改的表单
var formPanel=new Ext.form.FormPanel({
frame:true,
labelWidth:60,
labelAlign:'right',
items:[{
xtype:'fieldset',
title:'基本信息',
autoHeight:true,
defaults:{xtype:"textfield",width:300},
items:[
{xtype:"hidden",name:"ID"},
{fieldLabel:'编号',name:'plantID'},
{fieldLabel:'名称',name:'plantName'}]
}]
});
return formPanel;
},
//创建放置表单的窗口,见上图新增和修改的效果
createWin:function(){
return this.initWin(438,180,"污水厂管理");
//创建新增、添加面板
},
//指定JSON数据的mapping
storeMapping:["plantID","plantName"],

initComponent : function(){//初始化界面
var sm = new Ext.grid.CheckboxSelectionModel();
this.cm=new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),//获得行号
sm,
//定义GRID的表头信息
{header: "污水厂编号", sortable:true,width: 100, dataIndex:"plantID"},
{header: "污水厂名称", sortable:true,width: 200, dataIndex:"plantName"}
]);
AddPlantPanel.superclass.initComponent.call(this);
}
});

这样就完成了一个能应用到实际中的CRUD面板,效果见下图
[b]1.2与用户实现交互和与程序后台实现通信[/b]

EXT的组件在执行时是从initComponent开始的
我们来看看AddPlantPanel这个具体的CRUD面板的执行过程

initComponent : function(){
var sm = new Ext.grid.CheckboxSelectionModel();
this.cm=new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),//获得行号
sm,
//定义GRID的表头信息
{header: "污水厂编号", sortable:true,width: 100, dataIndex:"plantID"},
{header: "污水厂名称", sortable:true,width: 200, dataIndex:"plantName"}
]);
AddPlantPanel.superclass.initComponent.call(this);
}


首先是定义Grid表格的相关信息,接着是调用基类的initComponent方法,注意,EXT里面调用基类的方法是用superclass.方法名.call(this);
接着看基类方法里的initComponent
initComponent : function(){
//首先是定义数据源
this.store=new Ext.data.JsonStore({
id:"Id",
url: this.baseUrl+'?cmd=List',//默认的数据源地址,继承时需要提供
root: "rows",
totalProperty:"totalCount",
remoteSort:true,
fields:this.storeMapping});
this.cm.defaultSortable=true;//开启排序
this.sm= new Ext.grid.CheckboxSelectionModel(); //选择框
Mis.Ext.CrudPanel.superclass.initComponent.call(this);//初始化panel
var viewConfig=Ext.apply({forceFit:true},this.gridViewConfig); //添加配置信息
//Grid表格
this.grid=new Ext.grid.GridPanel({
store: this.store,
cm: this.cm,
sm:this.sm,
trackMouseOver:false,
loadMask: true,
viewConfig:viewConfig,
tbar: [……],//顶部工具栏
bbar: new Ext.PagingToolbar({
pageSize: 10,
store: this.store,
displayInfo: true,
displayMsg: '显示第 {0} - {1} 条记录,共 {2}条记录',
emptyMsg: "没有记录"
})//底部工具栏,放置分页信息
});
//双击时执行修改
this.grid.on("celldblclick",this.edit,this);
this.add(this.grid); //将Grid表格添加到panel内,很重要
this.store.load({params:{start:0,limit:10}});//Grid表格生成后,接着是加载数据,这里是与服务器端通信的关键
上面代码与服务器通讯的关键在于url: this.baseUrl+'?cmd=List',和this.store.load({params:{start:0,limit:10}});
url:指定了数据源的地址,在页面初始化时EXT调用this.store.load方法从this.baseUrl+'?cmd=List获取数据,参数为start=0&limit=10,即从 Plant.aspx?cmd=List& start=0&limit=10获取数据
当请求到达服务器端Plant.aspx?cmd=List& start=0&limit=10时(毕业设计用的.NET,其实后台都很简单),下面的代码执行
if(Request.Params["cmd"].ToString()=="List"){
int start =Convert.ToInt32(Request.Params["start"].ToString());
int limit = Convert.ToInt32(Request.Params["limit"].ToString());
string json = pnt.GetJsonAll(start, limit, "");
Response.Write(json);
}
//ps这是c#,php的以前发过,自己去找

上面的代码生成了一段JSON数据
{'totalCount':'5','rows': [{"plantID":"8","plantName":"ss"},{"plantID":"7","plantName":"7号污水处理厂修改 banben"},{"plantID":"23","plantName":"222"}, {"plantID":"22","plantName":"22"},{"plantID":"15","plantName":"15号污水处理 厂"}]}

EXT读取上面的JSON,兵将数据显示在表格中,这是与服务器的第一次通信
效果如下
[img]/upload/attachment/137590/45232a25-168f-36c2-851a-0f8d50298639.jpg[/img]
主要流程
[img]/upload/attachment/137592/441d2f65-0b8c-314e-9687-85f08f3157da.jpg[/img]

页面呈现给用户后接着就是与用户执行交互。

在Mis.Ext.CrudPane基类的初始化函数initComponent中有下面这段代码
tbar: [{
id:'addButton',
text: '新增',
iconCls:'addIconCss',
tooltip:'添加新纪录',
handler: this.create,
scope:this
},'-',//'-'给工具栏按钮之间添加'|'

{
id:'editButton',
text:'编辑',
iconCls:'editIconCss',
tooltip:'修改记录',
handler: this.edit,
scope:this
},'-',

{
text:'删除',
iconCls:'deleteIconCss',
tooltip:'删除所选中的信息',
handler: this.removeData,
scope:this

},'-',

{
text:'刷新',
iconCls:'refreshIcon',

tooltip:'刷新纪录',

handler: this.refresh,

scope:this

},'->',//'->'代表让工具栏按钮到右边去
'Search: ',this.name,

{text: '查询',pressed: true,


iconCls:'selectIconCss',


handler: this.search,

scope:this

},'
'

],


上面定义了面板顶部工具栏的按钮(效果见上图中的按钮),每个按钮都有一个handler,其参数是该类里的一个成员方法。当点击一个按钮时,便触发这个按钮handler对应的方法,比如点击新增,那么便会触发this.create方法,下面我们跟踪其执行路径。
见下面……

[img]/upload/attachment/137594/96b1165b-205c-355f-9795-43bb48a78774.jpg[/img]


[img]/upload/attachment/137596/b5326a78-f3b2-33c3-872b-f75be047aed0.jpg[/img]


[img]/upload/attachment/137598/340f61c3-8c25-3272-8d14-d9bcc56f33f4.jpg[/img]

首先是执行create方法,create方法如下


//创建(新增/修改)窗口

create:function()
{

this.showWin();//显示(新增/修改)窗口

this.reset();//清空表单里的数据

}

Create方法中有两个函数,依次执行

//显示(新增/修改)窗口

showWin:function()

{
//createForm()需要在继承时提供,该方法作用是创建表单

if(!this.win){

if(!this.fp){

this.fp=this.createForm();

}

this.win=this.createWin();

this.win.on("close",function(){this.win=null;this.fp=null;this.store.reload();},this);//添加事件,当窗口关闭时表格数据重新加载

}

//窗口关闭时,数据重新加载

this.win.show();

},


Showwin调用createWin()方法创建一个窗口,并将表单放在里面。而create里的第二个方法则是将表单的内容重置。这样就显示出了一个新增的画面

[img]/upload/attachment/137600/ede9f9e2-208b-3f4f-b754-498e8c234a5a.jpg[/img]


下面我们来看createWin()方法
//创建放置表单的窗口,见上图新增和修改的效果

createWin:function()

{


return this.initWin(438,180,"污水厂管理");

//创建新增、添加面板
},

该方法调用了initWin方法来创建窗口,为了更清晰的理解,我们再看看initWin方法
initWin:function(width,height,title)

{


var win=new Ext.Window({

width:width,

height:height,

buttonAlign:"center",

title:title,

modal:true,

shadow:true,

closeAction:"hide",

items:[this.fp],

buttons:[{text:"保存",


handler:this.save,


scope:this},


{text:"清空",


handler:this.reset,


scope:this},


{text:"关闭",


handler:this.closeWin,


scope:this}


]


});

return win;
},

注意
{text:"保存",
handler:this.save,
scope:this},

当用户填完数据点击保存时,触发save方法,于是EXT调用save方法

[img]/upload/attachment/137606/160c62c9-fe9a-3a0e-b31e-8b6978747c5c.jpg[/img]


//保存

save:function()

{


var id=this.fp.form.findField("ID").getValue();


this.fp.form.submit({

waitMsg:'正在保存。。。',


url:this.baseUrl+"?cmd="+(id?"Update":"Save"),


method:'POST',


success:function(form_instance_create, action) {


Ext.MessageBox.alert('友情提示', action.result.info);

},

failure:function(form_instance_create1, action1){


Ext.MessageBox.alert('友情提示', action1.result.info);


},


scope:this

});

},

效果

该方法实现了与ASP.NET后台通讯,将会把表单内的数据用POST方法传到baseUrl?cmd=Save中,因为上面的baseUrl是Plant.aspx,所以最终将数据传送到Plant.aspx?cmd=Save
[size=+0]EXT将数据传到了.NET后台,接着就是.NET后台处理EXT传来的数据,下面我们看看Plant.aspx怎么处理
Mis.BLL.Plant pnt = new Mis.BLL.Plant();

if (Request.Params["cmd"].ToString() == "Save")

{

string id = Request.Params["plantID"].ToString();

string name = Request.Params["plantName"].ToString();

Mis.Model.Plant pntm = new Mis.Model.Plant();

pntm.plantID = id;

pntm.plantName = name;

try

{

pnt.Add(pntm);

Response.Write("{success:true,info:'新增成功'}");

}catch (Exception adde){
Response.Write("{failure:true,info:'新增失败,错误原因为:" + this.addlashes((adde.Message.ToString())) + "'}");
}}

上面的方法实现了将信息保存到数据库,如果成功则返回"{success:true,info:'新增成功'}",这是一个JSON字符串。EXT获取返回的数据,成功就调用save中的:
success:function(form_instance_create, action) {
Ext.MessageBox.alert('友情提示', action.result.info);
},

效果

[img]/upload/attachment/137608/7e8fa5a7-47f4-3cbf-acd3-97d61b7d9f79.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值