去年这个时候写过一篇全自动数据表格的文章http://www.cnblogs.com/liuyh/p/5747331.html。文章对自己写的一个js组件做了个概述,很多人把它当作了一款功能相似的纯前端表格组件,然而这并不是我的初衷,我的本意是让后台系统的开发从重复的增删查改中脱离出来,我想即使不使用代码生成器也能做到极快速的开发。它不是优秀的表格组件,而是一个极简的增删查改解决方案。
为什么不使用现有的表格组件
成熟的表格组件有很多,功能强大的也有不少。它们都大大减少了我们的工作量,那么为什么我还要自己再折腾一个呢?因为还能减少更多...比如:
1、现有的绝大部分表格组件依然避免不了我们需要手写新增、编辑页面相关的代码。
2、即使有表格内部支持编辑模式,但是几乎都不支持图片和富文本格式。
3、对于查询和分页等功能很多都需要自己去实现,至少服务端如此。
其实不是表格的设计者们没有想到这些问题,而是要实现这些功能对于一个表格组件来说显得过重了,我想很多表格的使用者们也不能接受使用表格前先引入一个ueditor吧。但是对于我们来说,在轻量级表格与轻量级的工作面前,我想结果是显而易见的,这才是我写表格组件bode.grid.js的初衷。
如何省去新增和编辑页面
很多人有一个惯性的思维,认为每个表格的新增、编辑页面都不同,字段不同,字段的类型也不同,有些是数字,有些是下拉选择,有些又要上传图片,有些还是富文本,都不能提取共性,更何谈省去。万事万物都是有共性的,就像人与老虎同属哺乳动物,鸟和鸡都是鸟类,难道说人和鸟就没有共性么?不是的,他们都是生物。好吧,扯远了...看看这个数据结构,它能满足我们的要求:
[ { title:"名称", data:"字段名", type:"字段类型", value:"值" } ]
对于一个简单的form表单,这个结构足以描述。太复杂的页面?自己写...。而就我的实践经验告诉我,这个结构足以满足90%后台系统中的新增与修改。
共性提取出来了,现在所需要做的就是按字段类型渲染不同的组件,比如图片类型的上传插件、富文本类型的编辑器等,只是dom结构的拼接以及组件的初始化,示例代码如下:
this.initForm = function () { var form = $('<form >); form.appendTo($("body")); for (var i = 0, iLen = this.columns.length; i < iLen; i++) { var colType = this.columns[i]["type"]; if (!colType) continue; var row; if (["text", "number", "datepicker", "timepicker", "hide"].indexOf(colType) >= 0) { row = $('<div class="form-group"><label for="' + this.columns[i]["data"] + '" class="col-sm-3 control-label">' + this.columns[i]["title"] + ':</label><div class="col-sm-9"><input type="text" class="form-control" id="' + this.columns[i]["data"] + '"></div></div>'); if (colType === "number") { $.bode.tools.input.formatDiscount(row.find("#" + this.columns[i]["data"])); } else if (colType === "datepicker" || colType === "timepicker") { var showTime = colType === "timepicker"; $.bode.tools.input.formatTime(row.find("#" + this.columns[i]["data"]), showTime); } else if (colType === "hide") { row.hide(); } row.appendTo(form); } else if (["switch", "dropdown"].indexOf(colType) >= 0) { var source = this.columns[i]["source"]; var valueFiled = source.valueField || "value"; var textField = source.textField || "text"; row = $('<div class="form-group"><label for="' + this.columns[i]["data"] + '" class="col-sm-3 control-label">' + this.columns[i]["title"] + ':</label><div class="col-sm-9"><select class="form-control" id="' + this.columns[i]["data"] + '"></select></div></div>'); var select = row.find("#" + this.columns[i]["data"]); for (var j = 0, jLen = source["data"].length; j < jLen; j++) { var option = source["data"][j]; $('<option value="' + option[valueFiled] + '">' + option[textField ] + '</option>') .appendTo(select); } row.appendTo(form); } else if (colType === "img") { row = $('<div class="form-group"><label for="' + this.columns[i]["data"] + '" class="col-sm-3 control-label">' + this.columns[i]["title"] + ':</label><div class="col-sm-9"><div class="uploader-list"><div class="file-item thumbnail"><img style="width:160px;height:90px;" id="img_' + this.columns[i]["data"] + '" src="" /></div></div><div id="' + this.columns[i]["data"] + '">选择图片</div></div></div>'); row.appendTo(form); // 初始化Web Uploader var uploader = WebUploader.create({ auto: true, // 选完文件后,是否自动上传。 swf: '/Content/js/plugs/webuploader/Uploader.swf', // swf文件路径 server: this.imgSaveUrl, // 文件接收服务端。 // 选择文件的按钮。可选。 // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick: '#' + this.columns[i]["data"], // 只允许选择图片文件。 accept: { title: 'Images', extensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: 'image/*' } }); uploader.on("uploadSuccess", function (file, resp) { $("#img_" + this.options.pick.substring(1)).attr("src", resp); }); } else if (colType === "textarea") { row = $('<div class="form-group"><label for="' + this.columns[i]["data"] + '" class="col-sm-3 control-label">' + this.columns[i]["title"] + ':</label><div class="col-sm-9"><textarea class="form-control" id="' + this.columns[i]["data"] + '" style="overflow: hidden; word-wrap: break-word; resize: horizontal; height: 48px;"></textarea></div></div>'); row.appendTo(form); row.find('textarea').autosize({ append: "\n" }); } else if (colType === "richtext") { row = $('<div class="form-group"><label for="' + this.columns[i]["data"] + '" class="col-sm-3 control-label">' + this.columns[i]["title"] + ':</label><div class="col-sm-9"><textarea class="form-control" id="' + this.columns[i]["data"] + '" style="heght:150px;"></textarea></div></div>'); row.appendTo(form); var editor = new wangEditor(this.columns[i]["data"]); editor.config.uploadImgUrl = this.imgSaveUrl; editor.config.withCredentials = false; editor.create(); editorHash[this.columns[i]["data"]] = editor; } } $('<hr class="wide" />').appendTo(form); this.isFormInited = true; }
最后在公共的js里将整个表单加入页面上,这样就完成了省去新增和编辑页面的工作。页面是省去了,但是数据如何保存,试想我们一般的新增和编辑接口,其提交的数据结构大概是这样: