在写一个table的javascript插件, 开始使用的方法是将数据放入一个2纬数组里作参数传入插件,但发现使用这种方法后对于td中内容的格式化非常不利,尤其对于列存在变动的情况。
看看旧实现:
$.fn.table=function(titles, data, formatter, css) { formatter = formatter||function(data, row, col, val){return val+'';}; var html=["<table celspace='0' celpadding='0' border='0' >"],odd=""; html.push("<tr class='title'><th class='lineno' style='color:grey'>-</th>"); $.each(titles, function(i, title){ html.push('<th><div class="value">'+title+'</div></th>'); }); html.push("</tr>"); $.each(data, function(i, row){ odd=(odd==="")?" class='odd'":""; html.push("<tr"+odd+">"); html.push('<td class="lineno"><div class="value">'); html.push(i+1); html.push('</div></td>'); $.each(row, function(j, elm){ html.push('<td><div class="value">'); html.push(formatter(data, i, j, elm)); html.push('</div></td>'); }); html.push("</tr>"); }); html.push('<table>'); var table = $(html.join('')).appendTo(this.empty()); if(css) { table.addClass(css); } return this; };
旧的实现中,在formatter中格式化显示时,数据的获取变得非常混乱,都通过各种索引进行,可读性很差:
//如果列是固定的,这时要第3列和第2列进行百分比后显示,那么formatter是这样: function formatter(data, col, row, val) { return ((val / data[1] )* 100).toFixed(2) + '%'; } //如果列是变动的,比如刚开始显示的是小李的支出,1列是时间,2列为收入,3列为支出, //总列数为3列,每人显示两列,这时又把小刚的数据加了进来,那么就变成这样了5列(时间不用重复显示): function formatter(data, col, row, val) { var type = (col-1) % 2;//当前列对应的项; if(type == 1) {//这是支出(减去了时间1列,下标比真实列数少1所以是1) var i = col-1;// 收入等于上一列,即col-1 return ((val / data[i] )* 100).toFixed(2) + '%'; } else { // ... ... return ""; } }
看,这是不是非常之十分之超级麻烦 --!!!,更别说在此之前还要对data数组进行填充了。
再看看新的实现:
$.fn.table2 = function(col, row, titleGetter, dataGetter, css) { formatter = formatter||function(data, row, col, val){return val+'';}; var html=["<table celspace='0' celpadding='0' border='0' >"],odd=""; html.push("<tr class='title'><th class='lineno' style='color:grey'>-</th>"); for (var i = 0; i < col; i++) { html.push('<th><div class="value">'+titleGetter(i)+'</div></th>'); } html.push("</tr>"); for (var r = 0; r < row; r++) { odd=(odd==="")?" class='odd'":""; html.push("<tr"+odd+">"); html.push('<td class="lineno"><div class="value">'); html.push(r+1); html.push('</div></td>'); for (var c = 0; c < col; c++) { html.push('<td><div class="value">'); html.push(dataGetter(c, r)); html.push('</div></td>'); } html.push("</tr>"); } html.push('<table>'); var table = $(html.join('')).appendTo(this.empty()); if(css) { table.addClass(css); } };
新实现中,data已经不见踪影了, 数据获取仅通过行和列与回调函数进行,完全不用管数据格式,在dateGetter中数据的获取与格式化溶为一体,还可以方便的操纵原始对象,如:
var result = [ [{ts: 0, shou:1000, zhi:20 },{ts: 1, shou:1000, zhi:25 }],//小李 [{ts: 0, shou:1000, zhi:30 },{ts: 1, shou:1000, zhi:25 }],//小刚 ]; //每个人显示的总列数还是2列,时间额外1列。 function dataGetter(col, row) { if(col == 0) { return result[ 0 ][ row ].ts; } var persionIdx = Math.ceil((col-1) / 2);//第几个人 var persion = result[ persionIdx ];//对原始对象进行操作 var type = (col-1) % 2;//收入or支出 if(type == 0) { return persion.shou;//收入 } else if(type == 1) { return ((persion.zhi / persion.shou)*100).toFixed(2) + '%';//支出 } }
兼容旧实现:
$.fn.table=function(titles, data, formatter, css) { if(!data[0]) { this.empty(); } else { this.table2(data[0].length, data.length, function(col, row) { return titles[col]; }, function(col, row) { return formatter(data, col, row, data[row][col]); }); } };