前面一段时间发了一篇封装的EXT CRUD面板,地址为 http://www.phpchina .com/bbs/thread-59552-1-1.html
只是单纯的贴出了代码,对于其中的运行原理并未提及到,这篇文章将分享该CRUD面板实现原理,好了,不废话,正式开始。
下面的内容是毕业论文中的一部分,所以大家看看就是
EXT 做为与用户交互的前端,其功能可以概括为:生成用户界面,与用户实现交互,并与程序(PHP , .NET等) 后台通信来完成与用户的交互。下面就这几个功能的实现原理做介绍。
1.1
生成用户界面
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 面板,效果见下图
1.2
与用户实现交互和与 程序 后台实现通信
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,兵将数据显示在表格中,这是与服务器的第一次通信
效果如下
主要流程
页面呈现给用户后接着就是与用户执行交互。
在 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 方法,下面我们跟踪其执行路径。
见下面……
[ 本帖最后由 04007147 于 2008-5-21 23:15 编辑 ]
附件
-
success.JPG
(22.6 KB)
-
2008-5-21 22:58
-
save.JPG
(23.49 KB)
-
2008-5-21 22:58
-
wushui2.jpg
(30.71 KB)
-
2008-5-21 22:58
-
接上面……从word拷过来的,无用字符比较多
首先是执行 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 里的第二个方法则是将表单的内容重置。这样就显示出了一个新增的画面
下面我们来看 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 方法
//保存
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);
},
效果