ExtFrame里的Grid封装

ExtJS里的Grid是UI控件的一个亮点,但是用起来比较麻烦,要编写太多的配置项,创建Grid的地方往往代码很长很长

在设计框架时,就考虑了以下几点:

1、Grid要封装的尽可能的简单,创建Grid代码要简单(最关键的是要降低脚本代码量,提高脚本的可读性与维护性)

2、Grid项变更时要尽量简单

3、Grid扩展列显示样式时也要尽量简单些

4、要能配合Command模式的操作(支持在配置文件里刷新)

5、要支持Command列

最后就做了这么两个东西出来:

QueryGrid

QueryAllGrid

两者的区别是QueryAllGrid不带分页功能

后来又在这两个基础上继续继承了其他的Grid,例如带自动连接查询配置项的Grid

封装后,在遇到查询Grid时,就简单了

例如,用户查询时,上面是个用户查询条件的FormPanel(叫usersearchpanel),下面是个放置GridPanel的userquerypanel,里面放了个usergrid

userquerypanel代码是这么写的:

var userquerypanel = new Ext.Panel({
    width: '100%',
    height: 500,
    items: [usergrid]
});

usergrid是这么写的:

var usergrid = new QueryGrid({
    title: '查询结果',
    frame: true,
    moniker: 'UserInfo',
    gridName: 'user',
    queryPanel: usersearchpanel,
    width: '100%',
    height: 450
});

按钮条上有个查询按钮,代码就是"usergrid.read();"

当点击查询按钮时,usergrid就显示出查询结果了

也就是说,在前台,创建一个Grid,只需要给Grid三个参数:查询的数据类型,Grid的名字,查询参数的panel,就可以自动生成Grid的结果了

QueryGrid的构造代码是这样的:

View Code
 1 function QueryGrid(config) {
 2     this.moniker = config.moniker;
 3     this.gridName = config.gridName;
 4     this.pageSize = 20;
 5     if (config.pageSize != null) {
 6         this.pageSize = config.pageSize;
 7     }
 8     if (config.sm == null) {
 9         this.sm = new Ext.grid.CheckboxSelectionModel();
10     }
11     this.url = '/Query/Read';
12     if (config.url != null) {
13         this.url = config.url;
14     }
15     var cm = new Ext.grid.ColumnModel(eval(GridBuilder.getGridDef(config.gridName)));
16     var ds = new Ext.data.Store({
17         url: this.url,
18         listeners: {
19             loadexception: function(s1, s2, s3, s4) {
20                 alert('载入数据失败!' + Ext.util.JSON.decode(s3.responseText).msg);
21             }
22         },
23         reader: new Ext.data.JsonReader({ totalProperty: 'results', root: 'rows' }, eval(GridBuilder.getGridReader(config.gridName)))
24     });
25     config.cm = cm;
26     config.ds = ds;
27 
28     config.bbar = new Ext.PagingToolbar({
29         pageSize: this.pageSize,
30         store: ds,
31         displayInfo: true,
32         displayMsg: '第 {0} - {1} 条  共 {2} 条',
33         emptyMsg: "没有记录"
34     });
35     QueryGrid.superclass.constructor.call(this, config);
36 };
37 
38 Ext.extend(QueryGrid, Ext.grid.GridPanel, {
39     read: function() {
40         if ((this.queryPanel != null) && (this.querypanel != 'undefined')) {
41             var s = this.queryPanel.getForm().getValues(true);
42             Ext.apply(this.store.baseParams, { query: s });
43         }
44         Ext.apply(this.store.baseParams, { moniker: this.moniker, gridname: this.gridName });
45         this.store.load();
46     },
47     doDelete: function(id) {
48         var grid = this;
49         Ext.MessageBox.confirm('提示', '确认要删除该行么?', function(msgid) {
50             if (msgid == 'yes') {
51                 var requestconfig = {
52                     waitmsg: '正在删除数据',
53                     waitTitle: '提示',
54                     url: '/Data/Delete?Moniker=' + grid.moniker + '&ID=' + id,
55                     method: 'POST',
56                     success: function(form, action) {
57                         Ext.Msg.alert('提示', '删除成功');
58                         grid.store.load();
59                     },
60                     failure: function(form, action) {
61                         Ext.Msg.alert('提示', '删除失败:' + action.result.msg);
62                     }
63                 }
64                 Ext.Ajax.request(requestconfig);
65             }
66         });
67     }
68 });

QueryAllGrid少了个bbar,这样就不分页了

从代码里可以看到的是,QueryGrid的实例构造时,按提供的名称配置从GridBuilder里获取了这个Grid的定义,并将定义转化成为这个Grid的cm

也就是说,Grid的标题栏其实是配置出来的

然后QueryGrid提供了read这个刷新方法和doDelete这个删除指定数据的方法,这样在command里,就可以配置查询为grid.read,read时会把提供的FormPanel里的数据序列化后做为参数传递给后台

删除一行数据的功能为grid.doDelete({'id'})

GridBuilder这个类负责在系统启动后(进入页面时)通过Ajax操作一次性加载所有的表格的定义,然后提供给所有的表格

当然,其实也考虑过所有的表格可以选择开始时加载一个空的定义,然后显示时再通过Ajax操作获取本表的定义后通过reconfigure方法来重新设置表格列,这样启动时少载入些信息,也不需要GridBuilder,代价是每个表格要额外的访问一次表格定义

表格的列是通过配置文件定义的,成如下模式:(以用户示例)

  <Grid name="user" checkbox="true">
    <Column name="gender" caption="" type="common" field="Gender" width="40" render="gendercolumnrender"/>
    <Column name="username" align="left" caption="名称" type="common" field="UserName" width="100"/>
    <Column name="phone" caption="电话" type="common" field="Telephone" width="100"/>
    <Column name="mobile" caption="手机" type="common" field="Mobile" width="150"/>
    <Column name="email" caption="电子邮件" type="common" field="Email" width="200"/>
    <Column name="state" caption="状态" type="global" field="State" key="userstate" width="80"/>
    <Column name="address" caption="地址" type="common" field="address" width="100"/>
    <Column name="command" width="150" type="command" caption="操作" field="command" command="usergrid" />
  </Grid>

这样,如果要修正显示的列,无需修改代码,只需要修改配置文件(不过修改后要重启网站,因为配置文件是一次性加载的)

系统支持如下类型的列:

common,普通类型显示

image,字段的内容将被转换成对应的图形

global,把Int值转换成对应的字符串

foreign,外键连接字段,从外键KEY转换成对应的显示字段

link,显示成<a>样式,点击时执行里面设置的脚本

command,Command模式复用,根据指定的command创建操作列

在这些基础类型的列之外,如果我们遇到了特殊格式或要求的列(例如,要显示成美元$样式或人民币¥样式),则可以在列的属性上指定一个对应的render的IOC对象来处理

例如,编程时遇到个问题,就是日期控件保存到数据库里的数据,读出到Grid里时,显示的就是比较奇怪的字符串,这时可以加载一个render="datecolumnrender"并指定format格式为"yyyy-MM-dd",这个render的功能就是对每行的数据指定的字段,将其从源格式转换成日期字符串格式

遇到这些问题,就完全无需在前台对脚本进行改动来适应,也无需在逻辑层做任何处理,而只需要使用正确的render去处理

而在Controller层是如此处理的:

执行QueryController的Read方法时,首先获取参数,得到查询数据类型,然后根据配置获取该数据类型定义的SecurityHandler和DataHandler(参见核心设计模式之二),判断当前用户具备查询权限后,调用DataHandler的方法获取到结果,然后获取Grid的GridRender来对数据做渲染处理,这个GridRender前面没介绍,是负责对所有的列进行格式处理的,例如,把global列的Int值转换成对应的字符串,而如果一个列上定义了render,则GridRender会调用对应的ColumnRender来渲染这个列,最后,将渲染的结果生成Json数据传递给grid的store

总结:ExtFrame里的Grid封装有以下优点:

1、代码创建简单

2、封装的刷新、删除等功能易用

3、Grid修改简单

4、修改显示内容时无需修改代码

5、提供扩展显示容易

转载于:https://www.cnblogs.com/zuxOK/archive/2012/05/10/2494346.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值