其实我真心不想用EXT(个人认为EXT对程序员本身提高没有好处),虽然做过的这些项目很早就开始使用EXT,不过自己开发的模块还是尽量不去使用它。最近实在没办法了= =,为了整个系统界面统一,硬着头皮用吧~。一个列表的例子(EXT+DWR+SPRING),记录一下,以后EXT用的最多的还是列表~
列表用到Ext.data.DWRProxy类,需要引入:
1 | <script type="text/javascript" src="ext3/dwrproxy.js"></script> |
下面为前端的JS代码,其实网络提供的例子也很多了,不过大多为JsonReader,这里用的是ListRangeReader,基本代码都是大同小异:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | // 关键对象: // Ext.data.HttpProxy 创建访问服务端的代理 // Ext.data.Store 数据存储器 // Ext.grid.ColumnModel gridPanel呈现时,显示的列集合 // Ext.PagingToolbar gridPanel分页 // Ext.grid.GridPanel 数据呈现 /** ******************自动行号******************* */ var rownumber = new Ext.grid.RowNumberer(); /** ******************每页显示数量******************* */ var gridPageSize = 15; /** ******************主页面******************* */ var nav = null; /** ******************搜索表单的下拉列表******************* */ var arrayStore_data_19 = { zblxData : [['1', '交通工具'], ['2', '勘察工具'], ['3', '通讯工具'], ['4', '执法用品'], ['4', '其它']], syData : [['1', '是'], ['2', '否']] } var arrayStore_19 = { zblxStore : new Ext.data.ArrayStore({ data : arrayStore_data_19.zblxData, fields : ['id', 'name'] }), syStore : new Ext.data.ArrayStore({ data : arrayStore_data_19.syData, fields : ['id', 'name'] }) } /** ******************查询过滤******************* */ var filter = { filters : new Array(), getSearchExpressions : function() { var expressions = new Array(); // 遍历表单设置查询项 var form = document.forms[0]; for (var i = 0; i < form.length; i++) { var element = form[i]; if (element != '' && element != null && element.value != "" && element.value != null) { // 再过滤一下查询项 if (element.name == "zbmc" || element.name == "zblb" || element.name == "zbxh" || element.name == "sfsh" || element.name == "syr" || element.name == "jg") { expressions.push({ name : element.name, // op : 'eq', op : 'like', stringValue : '%' + element.value + '%' }); } } } filter.filters = expressions; }, setFilter : function(proxy, params) { filter.getSearchExpressions(); var args = new Array(); if (filter.filters != null) { for (var i = 0; i < filter.filters.length; i++) { args.push(filter.filters[i]); } } params.args = [args]; } } /** ******************数据 需要引入 dwrproxy.js******************* */ var store_19 = function() { var proxy = new Ext.data.DWRProxy(xzzfZfzbDwrService.getXzzfList, true); proxy.on('beforeload', function(proxy, params) { filter.setFilter(proxy, params) }, this); // 列准备 var listType = Ext.data.Record.create([{ name : "id", type : "int" }, { name : "ctime", mapping : "ctime", type : "string" }, { name : "etime", mapping : "etime", type : "string" }, { name : "jg", mapping : "jg", type : "string" }, { name : "sfsh", mapping : "sfsh", type : "string" }, { name : "syr", mapping : "syr", type : "string" }, { name : "userid", mapping : "userid", type : "string" }, { name : "zbjj", mapping : "zbjj", type : "string" }, { name : "zblb", mapping : "zblb", type : "string" }, { name : "zbmc", mapping : "zbmc", type : "string" }, { name : "zbxh", mapping : "zbxh", type : "string" }]); var ds = new Ext.data.Store({ proxy : proxy, reader : new Ext.data.ListRangeReader({ id : 'id', root : "data", totalProperty : 'totalSize' }, listType), // true为后台排序,如果是false只在前台获取的数据排序 remoteSort : true }) ds.setDefaultSort("etime", "desc"); return { getStore : function() { return ds; } } } var store = new store_19(); var ds = store.getStore(); /** ******************列表******************* */ var list_19 = function() { // 标题处理 function titleFormater(value, metadata, record, rowIndex, colIndex, store) { if (value == '') { value = '无标题' } value = '<a href="../editPre/' + record.id + '" title="' + value + '">' + value + '</a>'; return value; } var columnModel = new Ext.grid.ColumnModel([rownumber, { header : '装备名称', align : 'center', width : 220, sortable : true, dataIndex : 'zbmc', renderer : titleFormater }, { header : '装备类别', align : 'center', sortable : true, dataIndex : 'zblb' }, { header : '装备序号', align : 'center', width : 220, sortable : true, dataIndex : 'zbxh' }, { header : '是否使用', align : 'center', sortable : true, dataIndex : 'sfsh' }, { header : '使用人', align : 'center', sortable : true, dataIndex : 'syr' }, { header : '使用机构', align : 'center', sortable : true, dataIndex : 'jg' }]); columnModel.defaultSortable = true; return { getColumnModel : function() { return columnModel; } } } var list = new list_19(); var cm = list.getColumnModel(); /** ******************Panel******************* */ var panel_19 = function() { var listgrid = new Ext.grid.GridPanel({ store : ds, cm : cm, autoHeight : true, autoWidth : true, bodyStyle : 'width:100%', stripeRows : true, border : false, loadMask : { msg : '数据载入中...' }, tbar : new Ext.PagingToolbar({ pageSize : gridPageSize, store : ds, displayInfo : true, displayMsg : '执法装备列表 {0} - {1} 共 {2} 条', emptyMsg : "没有记录", firstText : "首页", lastText : "末页", nextText : "下一页", prevText : "上一页", refreshText : "刷新", afterPageText : '页 共{0}页', beforePageText : '第' }), bbar : new Ext.PagingToolbar({ pageSize : gridPageSize, store : ds, displayInfo : true, displayMsg : '执法装备列表 {0} - {1} 共 {2} 条', emptyMsg : "没有记录", firstText : "首页", lastText : "末页", nextText : "下一页", prevText : "上一页", refreshText : "刷新", afterPageText : '页 共{0}页', beforePageText : '第' }) }); var mainPanel = new Ext.Panel({ collapsible : true, title : '执法装备列表', items : [listgrid] }); return { getPanel : function() { return mainPanel; } } } var panel = new panel_19(); var mainPanel = panel.getPanel(); /** ******************按钮函数******************* */ var buttonAction = { search : function() { ds.load({ params : { start : 0, limit : gridPageSize } }); }, add : function() { window.location.href = "../addPre/"; }, reset : function() { nav.form.reset(); } } /** ******************查询表单******************* */ var form_19 = { // 第一行表单 items1 : { // 行1 layout : "column", // 从左往右的布局 items : [{ columnWidth : .3, // 该列有整行中所占百分比 layout : "form", // 从上往下的布局 items : [{ xtype : "textfield", fieldLabel : "装备名称", name : 'zbmc', width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "combo", fieldLabel : "装备类别", name : 'zblb', store : arrayStore_19.zblxStore, valueField : 'name', displayField : "name", mode : "local", width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "装备序号", name : 'zbxh', width : 100 }] }] }, // 第二行表单 items2 : { // 行2 layout : "column", // 从左往右的布局 items : [{ columnWidth : .3, // 该列有整行中所占百分比 layout : "form", // 从上往下的布局 items : [{ xtype : "combo", fieldLabel : "是否使用", name : 'sfsh', store : arrayStore_19.syStore, valueField : 'name', displayField : "name", mode : "local", width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "使用人", name : 'syr', width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "所属机构", name : 'jg', width : 100 }] }] }, // 第二行按钮 button : { bodyStyle : 'padding:0px', buttonAlign : 'center', buttons : [{ text : '开始查询', handler : function() { buttonAction.search(); } }, { text : '清空查询项', handler : function() { buttonAction.reset(); } }, { text : '添加装备', handler : function() { buttonAction.add(); } }] } } Ext.onReady(function() { // 主页面 nav = new Ext.form.FormPanel({ title : '执法装备管理', frame : true, border : true, x : 0, y : 0, renderTo : Ext.getBody(), items : [form_19.items1, form_19.items2, form_19.button, // 行4 mainPanel] }); // 第一次刷新数据 buttonAction.search(); }); // xzzfZfzbDwrService.getXzzfList(null, 0, 10, null, result); // function result(data) { // alert(data.totalSize); // alert(data.data); // alert(data.data[0]); // alert(data.data[0].zbmc); // alert(data.data[0].zblb); // alert(data.data[0].zbxh); // alert(data.data[0].sfsh); // alert(data.data[0].syr); // alert(data.data[0].jg); // } |
关于这段JS的细节记录:
var rownumber = new Ext.grid.RowNumberer();EXT本身的序列生成器,用于列表。
gridPageSize 每页显示的列表条数。
filter用于过滤表单并生成查询项,查询项本身的生成方法有很多,这里只是我的写法。此查询队列会被DWRProxy提交到后台。这里的查询队列中每个查询对象有三个属性:name,op,stringValue,后台需要根据这三个属性生成相应的查询语句。
之后便是Ext.data.Store,需要设置三个对象:proxy,类似于new Ext.data.DWRProxy(xzzfZfzbDwrService.getXzzfList, true);,xzzfZfzbDwrService.getXzzfList就是DWR注册的可调用的方法。reader : new Ext.data.ListRangeReader 为服务端返回的数据,设置返回数据的根root : “data”,数据的长度大小totalProperty : ‘totalSize’,数据列的对应mapping:listType,listType需要对应为你返回的bean中的name。
其中remoteSort : true,true为后台排序,每次点击标题头都会从后台根据排序方式重新获取数据,如果是false只在前台获取的当前列表的数据排序。
ds.setDefaultSort(“etime”, “desc”);为默认的排序方法,此方法会用参数传递到后台。
proxy.on(‘beforeload’, function(proxy, params) 表示在load数据前做的相关操作,这里的操作就是设置查询项。
之后便是设置GridPanel,包括标题头ColumnModel,前进后退栏PagingToolbar,整个查询的表单FormPanel,这块没什么说的,照着写就行了。
第一次打开页面执行buttonAction.search();来获取初始数据。
下边是后台的写法
首先需要写一个EXT的ListRange BEAN 并在dwrServlet.xml中注册,Ext.data.DWRProxy接收返回的数据类型便是此BEAN。如上所述的(xzzfZfzbDwrService.getXzzfList),需要两个基本对象,totalSize和data。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class ListRange implements Serializable { private Object[] data; private int totalSize public Object[] getData() { return data; } public void setData(Object[] data) { this.data = data; } public int getTotalSize() { return totalSize; } public void setTotalSize(int totalSize) { this.totalSize = totalSize; } } |
还需要写一个查询项的bean,类似于:
1 2 3 4 5 6 7 | public class Expression { private String name; private String op; private Object value; get set...... |
之后就是具体的外部调用的xzzfZfzbDwrService.getXzzfList的写法,类似于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public ListRange getXzzfList(Expression[] expressions, int startPosition, int maxResults, String orderBy) throws Exception { //startPosition及maxResults是EXT根据当前页数及每页显示的条数提交过来的数据。 //expressions为遍历的表单后的查询项 如上所述此查询队列每个查询对象有三个属性 name,op,stringValue //可以根据这三个属性循环遍历出队列的查询语句例如 Object query = null; for (int i = 0; i < expressions.length; i++) { String name = expression.getName(); String op = expression.getOp(); String value = expression.getValue(); //创建查询语句 query = ....; } //orderBy为EXT中DS设置的ds.setDefaultSort("etime", "desc"); 如果你Ext.data.Store的remoteSort设置为true,则每次点击标题头也会根据标题头的dataIndex的值传入类似于 "dataIndex desc"的排序语句。 //orderBy为一个简单的字符串如"etime desc",可以用切字符串的方法对排序进行进一步处理,或者直接使用这个排序字符,下边是一个进一步处理的例子: int pos = orderBy.indexOf(' '); String field = orderBy.substring(0, pos); String dir = orderBy.substring(pos + 1); if ("asc".equalsIgnoreCase(dir)) { ...... } else { ...... } //之后便是获取ListRange的两个基本数据 int count = count(query); //注意此查询出的bean需要在dwr中注册 List<bean> items = find(orderBy, startPosition, maxResults, query); //封装返回 ListRange result = new ListRange(); result.setTotalSize(count); result.setData(items.toArray()); return result; } |
最后就是注册Spring的dwrServlet.xml,包括注册外部调用的方法,需要封装的BEAN,这块就不细说了。别忘记还需要注册返回到EXT中的ListRange。
1 2 | <dwr:convert class="ListRange" type="bean"/> <dwr:convert class="YouBean" type="bean"/> |
近期评论