在开发WEB前端页面时,经常会根据动态的数据加载一些HTML控件,如果把这些HTML代码全写入JS中,根据不同的数据显示的控件也不一样,操作起来会显得比较繁琐,而且极不利于代码的维护,怎么办呢?现在就是我要说的,使用模板方法,直接把数据往里面套就好了。废话不多说,以示例来说明。
先写个非常重要的JS方法,此方法就是用来填充格式数据的。(看不懂也没关系,会用就行)
1 function formatTemplate(dta, tmpl) { 2 var format = { 3 name: function(x) { 4 return x 5 } 6 }; 7 return tmpl.replace(/{(w+)}/g, function(m1, m2) { 8 if (!m2) 9 return ""; 10 return (format && format[m2]) ? format[m2](dta[m2]) : dta[m2]; 11 }); 12 }
接下来就用示例来说明:
例如:从服务器取出一个JSON串,把数据显示在一组HTML控件上,现在我先把HTML代码写下来:
-
1 <script type="text/template"> 2 <tr mgid="{mgid}" mid="{mid}"> 3 <td> 4 <input type="checkbox" mid="{mid}"></td> 5 <td> 6 <a href="{localfile}" data-fancybox-group="button" class="fancybox-buttons"> 7 <img src="{localfile}" style="45px;height:45px;"></a> 8 </td> 9 <td> 10 <input type="text" class="input-large valid" value="{medianame}" onblur="TextOnBlur(this)" onclick="TextOnFocus(this)" name="medianame" mid="{mid}" readonly="readonly"></td> 11 <td> 12 <a onclick="updateMediaName(this)" href="javascript:void(0);">重命名</a> 13 <a onclick="showbulkUploadTemplate(this)" name="edit" localfile="{localfile}" href="javascript:void(0);">替换</a> 14 <a onclick="daleteMedia(this)" href="javascript:void(0);">删除</a> 15 <a onclick="setMediaFaceImage(this);" title="设置为分组【{groupname}】的封面" groupname="{groupname}" mid="{mid}" href="javascript:void(0);">设置封面</a> 16 </td> 17 </tr> 18 </script>
大家看到了这段代码,如果全部写JS上确实比较烦,而且大家也发现了,为什么在首尾有<script>标签,里面有{}括号括住了一些值,为什么这么写呢,别急别急。其实这些{}号中的数据,就是我们要填充的数据的地方。括号中的名称就是存贮值的变量,好,要怎么填呢?
若我们从服务器上取到的JSON如下:
-
1 { 2 "total": "1", 3 "page": "1", 4 "records": "3", 5 "rows": [{ 6 "groupname": "美食图片", 7 "mid": 4766, 8 "sid": 517, 9 "medianame": "Tulips", 10 "mgid": 549, 11 "mediatype": "image", 12 "mediaid": "", 13 "timestamp": "", 14 "localfile": "/UploadFile/image/201409/14/0x6dvf.jpg", 15 "picurl": "", 16 "thumbid": "", 17 "voiceformat": "", 18 "state": 1, 19 "createtime": "/Date(1410673220000+0800)/", 20 "uploadtime": "/Date(1410673220000+0800)/", 21 "width": 480, 22 "height": 360, 23 "seizespace": 17.41 24 }, { 25 "groupname": "美食图片", 26 "mid": 4765, 27 "sid": 517, 28 "medianame": "Penguins", 29 "mgid": 549, 30 "mediatype": "image", 31 "mediaid": "", 32 "timestamp": "", 33 "localfile": "/UploadFile/image/201409/14/6iluw6.jpg", 34 "picurl": "", 35 "thumbid": "", 36 "voiceformat": "", 37 "state": 1, 38 "createtime": "/Date(1410673215000+0800)/", 39 "uploadtime": "/Date(1410673215000+0800)/", 40 "width": 480, 41 "height": 360, 42 "seizespace": 15.62 43 }, { 44 "groupname": "美食图片", 45 "mid": 4764, 46 "sid": 517, 47 "medianame": "Lighthouse", 48 "mgid": 549, 49 "mediatype": "image", 50 "mediaid": "", 51 "timestamp": "", 52 "localfile": "/UploadFile/image/201409/14/fx0kzp.jpg", 53 "picurl": "", 54 "thumbid": "", 55 "voiceformat": "", 56 "state": 1, 57 "createtime": "/Date(1410673209000+0800)/", 58 "uploadtime": "/Date(1410673209000+0800)/", 59 "width": 480, 60 "height": 360, 61 "seizespace": 14.2 62 }] 63 } 64
我们要填写到地方定义在下面Table中
-
<html> <body> <table id="tableData"> <tr class="firstLine"> <th></th> <th>图片</th> <th>图片名称</th> <th>类型</th> <th>大小</th> <th>尺寸</th> <th>上传日期</th> <th>操作</th> <th></th> </tr> </table> </body> </html>
好了准备工作做好了,重点的来了,别看走眼了:
-
1 $.ajax({ 2 url: '/manage/GetAllMediaListPage', 3 type: 'get', 4 data: data, 5 cache: false, 6 dataType: "json", 7 success: function(dta) { 8 if (!dta || !dta.rows || dta.rows.length <= 0) { 9 return; 10 } 11 12 //获取模板上的HTML 13 var html = $('script[type="text/template"]').html(); 14 //定义一个数组,用来接收格式化合的数据 15 var arr = []; 16 //对数据进行遍历 17 $.each(dta.rows, function(i, o) { 18 //这里取到o就是上面rows数组中的值, formatTemplate是最开始定义的方法. 19 arr.push(formatTemplate(o, html)); 20 }); 21 //好了,最后把数组化成字符串,并添加到table中去。 22 $('#tableData').append(arr.join('')); 23 //走完这一步其实就完成了,不会吧,这么简单,不错,就是这么简单!! 不信就自己动手去试试! 24 } 25 });
哟嚯,搞定,等等,好像表格的列数对不上,是吧,那是因为我没有把模板写完整出来,继续往下看。
现在我来解释为什么把模板代码放在<script></script>中间,假如,你把模板代码放在某个<div>中并隐藏起来,那么可能你的代码中会用到$('input[type="text"]')查找控件时,不好意思,就会把模板中的也统计进去了,这个并不是你想要的。所以我用<script>,这么做还有一个好处,就是不会被当成HTML来执行显示出来, 但我们也得保证不能当成js来执行,所以加了个type="text/template",没有这个类型的,自己明白就好了。
另外,像o.mid的数值只会填充到{mid}这个里,不会填充到别的地方去,而且{mid}可以存在多个,一并全部替换成实际数值了。
接下来的一个问题就是,我取到的数据可能并不是我要给用户显示的,那么就需要变通一下了
-
1 var html = $('script[type="text/template"]').html(); 2 var arr = []; 3 $.each(dta.rows, function(i, o) { 4 //atime,asize和fsize这三个变量是之前的JSON中没有的,可灵活设置一下: 5 //格式化时间,当然getFormatDate这个函数我也公布出来了,格式化时间而已,见最后面。 6 o.atime = getFormatDate(o.uploadtime ? o.uploadtime : o.createtime, 'yyyy-MM-dd'); 7 //图片的尺寸大小: 就是把上面的o.width和o.height变量组合一下,如果任何一个不存在,则返回"-" 8 o.asize = (o.width && o.height) ? o.width + ' * ' + o.height : '-'; 9 //图片大小。存在才显示xxKB 10 o.fsize = o.seizespace ? o.seizespace + ' KB' : '-'; 11 //格式化模板数据 12 arr.push(formatTemplate(o, html)); 13 }); 14 $('#tableData').append(arr.join(''));
完整的HTML模板如下:
-
1 <script type="text/template"> 2 <tr mgid="{mgid}" mid="{mid}"> 3 <td> 4 <input type="checkbox" mid="{mid}"></td> 5 <td> 6 <a href="{localfile}" data-fancybox-group="button" class="fancybox-buttons"> 7 <img src="{localfile}" style="45px;height:45px;"></a> 8 </td> 9 <td> 10 <input type="text" class="input-large valid" value="{medianame}" onblur="TextOnBlur(this)" onclick="TextOnFocus(this)" name="medianame" mid="{mid}" readonly="readonly"></td> 11 <td>{mediatype}</td> 12 <!-- 各位看官,自定义的三个属性在这里哦~~ --> 13 <td>{fsize}</td> 14 <td>{asize}</td> 15 <td>{atime}</td> 16 <td> 17 <a onclick="updateMediaName(this)" href="javascript:void(0);">重命名</a> 18 <a onclick="showbulkUploadTemplate(this)" name="edit" localfile="{localfile}" href="javascript:void(0);">替换</a> 19 <a onclick="daleteMedia(this)" href="javascript:void(0);">删除</a> 20 <a onclick="setMediaFaceImage(this);" title="设置为分组【{groupname}】的封面" groupname="{groupname}" mid="{mid}" href="javascript:void(0);">设置封面</a> 21 </td> 22 </tr> 23 </script>
其实想通了还是挺简单的,当然formatTemplate函数中的第一个参数必须要求是像struct的对象,直接一点就是这样一个数据包: { "A": “a”, "B": "b", "C":"c" } 。懂了吧伙计们,不懂就慢慢看吧,嘿嘿!
附: 格式化时间函数:
-
1 function getFormatDate(xdate, format) { 2 try { 3 var format = format || 'yyyy-MM-dd HH:mm:ss'; 4 var date = (xdate instanceof Date) ? xdate : new Date(parseInt(xdate.replace('/Date(', '').replace(')/', ''), 10)); 5 var lang = { 6 'M+': date.getMonth() + 1, 7 'd+': date.getDate(), 8 'H+': date.getHours(), 9 'm+': date.getMinutes(), 10 's+': date.getSeconds() 11 }; 12 if (/(y+)/.test(format)) { 13 format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); 14 } 15 for (var key in lang) { 16 if (new RegExp('(' + key + ')').test(format)) { 17 format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? 18 lang[key] : ('00' + lang[key]).substr(('' + lang[key]).length)); 19 } 20 } 21 return format; 22 } catch (e) { 23 return '-'; 24 } 25 }