0%

JS使用模板快速填充HTML控件数据

在开发WEB前端页面时,经常会根据动态的数据加载一些HTML控件,如果把这些HTML代码全写入JS中,根据不同的数据显示的控件也不一样,操作起来会显得比较繁琐,而且极不利于代码的维护,怎么办呢?现在就是我要说的,使用模板方法,直接把数据往里面套就好了。废话不多说,以示例来说明。

先写个非常重要的JS方法,此方法就是用来填充格式数据的。(看不懂也没关系,会用就行)

Js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
function formatTemplate(dta, tmpl) {  
var format = {
name: function(x) {
return x
}
};
return tmpl.replace(/{(\w+)}/g, function(m1, m2) {
if (!m2)
return “”;
return (format && format[m2]) ? format[m2](dta[m2]) : dta[m2];
});
}
`

接下来就用示例来说明:
例如:从服务器取出一个JSON串,把数据显示在一组HTML控件上,现在我先把HTML代码写下来:
Html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script type=“text/template”>  
<tr mgid=“{mgid}” mid=“{mid}”>
<td>
<input type=“checkbox” mid=“{mid}”></td>
<td>
<a href=“{localfile}” data-fancybox-group=“button” class=“fancybox-buttons”>
<img src=“{localfile}” style=“width:45px;height:45px;”></a>
</td>
<td>
<input type=“text” class=“input-large validvalue=“{medianame}” onblur=“TextOnBlur(this)” onclick=“TextOnFocus(this)” name=“medianame” mid=“{mid}” readonly=“readonly”></td>
<td>
<a onclick=“updateMediaName(this)” href=“javascript:void(0);”>重命名</a>
<a onclick=“showbulkUploadTemplate(this)” name=“edit” localfile=“{localfile}” href=“javascript:void(0);”>替换</a>
<a onclick=“daleteMedia(this)” href=“javascript:void(0);”>删除</a>
<a onclick=“setMediaFaceImage(this);” title=“设置为分组【{groupname}】的封面” groupname=“{groupname}” mid=“{mid}” href=“javascript:void(0);”>设置封面</a>
</td>
</tr>
</script>

大家看到了这段代码,如果全部写JS上确实比较烦,而且大家也发现了,为什么在首尾有<script>标签,里面有{}括号括住了一些值,为什么这么写呢,别急别急。其实这些{}号中的数据,就是我们要填充的数据的地方。括号中的名称就是存贮值的变量,好,要怎么填呢?
若我们从服务器上取到的JSON如下:
Js代码

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
{  
“total”: “1”,
“page”: “1”,
“records”: “3”,
“rows”: [{
“groupname”: “美食图片”,
“mid”: 4766,
“sid”: 517,
“medianame”: “Tulips”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/0x6dvf.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673220000+0800)\/”,
“uploadtime”: “\/Date(1410673220000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 17.41
}, {
“groupname”: “美食图片”,
“mid”: 4765,
“sid”: 517,
“medianame”: “Penguins”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/6iluw6.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673215000+0800)\/”,
“uploadtime”: “\/Date(1410673215000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 15.62
}, {
“groupname”: “美食图片”,
“mid”: 4764,
“sid”: 517,
“medianame”: “Lighthouse”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/fx0kzp.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673209000+0800)\/”,
“uploadtime”: “\/Date(1410673209000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 14.2
}]
}

我们要填写到地方定义在下面Table中
Html代码

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
<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>

好了准备工作做好了,重点的来了,别看走眼了:
Js代码
$.ajax({
url: ‘/manage/GetAllMediaListPage’,
type: ‘get’,
data: data,
cache: false,
dataType: “json”,
success: function(dta) {
if (!dta || !dta.rows || dta.rows.length <= 0) {
return;
}

//获取模板上的HTML
var html = $(‘script[type=”text/template”]’).html();
//定义一个数组,用来接收格式化合的数据
var arr = [];
//对数据进行遍历
$.each(dta.rows, function(i, o) {
//这里取到o就是上面rows数组中的值, formatTemplate是最开始定义的方法.
arr.push(formatTemplate(o, html));
});
//好了,最后把数组化成字符串,并添加到table中去。
$(‘#tableData’).append(arr.join(”));
//走完这一步其实就完成了,不会吧,这么简单,不错,就是这么简单!! 不信就自己动手去试试!
}
});

哟嚯,搞定,等等,好像表格的列数对不上,是吧,那是因为我没有把模板写完整出来,继续往下看。
现在我来解释为什么把模板代码放在<script></script>中间,假如,你把模板代码放在某个<div>中并隐藏起来,那么可能你的代码中会用到$(‘input[type=”text”]’)查找控件时,不好意思,就会把模板中的也统计进去了,这个并不是你想要的。所以我用<script>,这么做还有一个好处,就是不会被当成HTML来执行显示出来, 但我们也得保证不能当成js来执行,所以加了个type=”text/template”,没有这个类型的,自己明白就好了。
另外,像o.mid的数值只会填充到{mid}这个里,不会填充到别的地方去,而且{mid}可以存在多个,一并全部替换成实际数值了。

接下来的一个问题就是,我取到的数据可能并不是我要给用户显示的,那么就需要变通一下了

Js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var html = $(‘script[type=”text/template”]’).html();  
var arr = [];
$.each(dta.rows, function(i, o) {
//atime,asize和fsize这三个变量是之前的JSON中没有的,可灵活设置一下:
//格式化时间,当然getFormatDate这个函数我也公布出来了,格式化时间而已,见最后面。
o.atime = getFormatDate(o.uploadtime ? o.uploadtime : o.createtime, ‘yyyy-MM-dd’);
//图片的尺寸大小: 就是把上面的o.width和o.height变量组合一下,如果任何一个不存在,则返回”-“
o.asize = (o.width && o.height) ? o.width + ‘ * ‘ + o.height : ‘-‘;
//图片大小。存在才显示xxKB
o.fsize = o.seizespace ? o.seizespace + ‘&nbsp; KB’ : ‘-‘;
//格式化模板数据
arr.push(formatTemplate(o, html));
});
$(‘#tableData’).append(arr.join(”));

完整的HTML模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type=“text/template”>  
<tr mgid=“{mgid}” mid=“{mid}”>
<td>
<input type=“checkbox” mid=“{mid}”></td>
<td>
<a href=“{localfile}” data-fancybox-group=“button” class=“fancybox-buttons”>
<img src=“{localfile}” style=“width:45px;height:45px;”></a>
</td>
<td>
<input type=“text” class=“input-large validvalue=“{medianame}” onblur=“TextOnBlur(this)” onclick=“TextOnFocus(this)” name=“medianame” mid=“{mid}” readonly=“readonly”></td>
<td>{mediatype}</td>
<!– 各位看官,自定义的三个属性在这里哦~~ –>
<td>{fsize}</td>
<td>{asize}</td>
<td>{atime}</td>
<td>
<a onclick=“updateMediaName(this)” href=“javascript:void(0);”>重命名</a>
<a onclick=“showbulkUploadTemplate(this)” name=“edit” localfile=“{localfile}” href=“javascript:void(0);”>替换</a>
<a onclick=“daleteMedia(this)” href=“javascript:void(0);”>删除</a>
<a onclick=“setMediaFaceImage(this);” title=“设置为分组【{groupname}】的封面” groupname=“{groupname}” mid=“{mid}” href=“javascript:void(0);”>设置封面</a>
</td>
</tr>
</script>

其实想通了还是挺简单的,当然formatTemplate函数中的第一个参数必须要求是像struct的对象,直接一点就是这样一个数据包: { “A”: “a”, “B”: “b”, “C”:”c” } 。懂了吧伙计们,不懂就慢慢看吧,嘿嘿!

附: 格式化时间函数:

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
function getFormatDate(xdate, format) {  
try {
var format = format || ‘yyyy-MM-dd HH:mm:ss’;
var date = (xdate instanceof Date) ? xdate : new Date(parseInt(xdate.replace(‘/Date(‘, ”).replace(‘)/’, ”), 10));
var lang = {
‘M+’: date.getMonth() + 1,
‘d+’: date.getDate(),
‘H+’: date.getHours(),
‘m+’: date.getMinutes(),
‘s+’: date.getSeconds()
};
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1, (date.getFullYear() + ”).substr(4RegExp.$1.length));
}
for (var key in lang) {
if (new RegExp(‘(‘ + key + ‘)’).test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ?
lang[key] : (’00’ + lang[key]).substr((” + lang[key]).length));
}
}
return format;
} catch (e) {
return ‘-‘;
}
}

在开发WEB前端页面时,经常会根据动态的数据加载一些HTML控件,如果把这些HTML代码全写入JS中,根据不同的数据显示的控件也不一样,操作起来会显得比较繁琐,而且极不利于代码的维护,怎么办呢?现在就是我要说的,使用模板方法,直接把数据往里面套就好了。废话不多说,以示例来说明。

先写个非常重要的JS方法,此方法就是用来填充格式数据的。(看不懂也没关系,会用就行)
Js代码

1
2
3
4
5
6
7
8
9
10
11
12
function formatTemplate(dta, tmpl) {  
var format = {
name: function(x) {
return x
}
};
return tmpl.replace(/{(\w+)}/g, function(m1, m2) {
if (!m2)
return “”;
return (format && format[m2]) ? format[m2](dta[m2]) : dta[m2];
});
}

接下来就用示例来说明:
例如:从服务器取出一个JSON串,把数据显示在一组HTML控件上,现在我先把HTML代码写下来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script type=“text/template”>  
<tr mgid=“{mgid}” mid=“{mid}”>
<td>
<input type=“checkbox” mid=“{mid}”></td>
<td>
<a href=“{localfile}” data-fancybox-group=“button” class=“fancybox-buttons”>
<img src=“{localfile}” style=“width:45px;height:45px;”></a>
</td>
<td>
<input type=“text” class=“input-large validvalue=“{medianame}” onblur=“TextOnBlur(this)” onclick=“TextOnFocus(this)” name=“medianame” mid=“{mid}” readonly=“readonly”></td>
<td>
<a onclick=“updateMediaName(this)” href=“javascript:void(0);”>重命名</a>
<a onclick=“showbulkUploadTemplate(this)” name=“edit” localfile=“{localfile}” href=“javascript:void(0);”>替换</a>
<a onclick=“daleteMedia(this)” href=“javascript:void(0);”>删除</a>
<a onclick=“setMediaFaceImage(this);” title=“设置为分组【{groupname}】的封面” groupname=“{groupname}” mid=“{mid}” href=“javascript:void(0);”>设置封面</a>
</td>
</tr>
</script>

大家看到了这段代码,如果全部写JS上确实比较烦,而且大家也发现了,为什么在首尾有<script>标签,里面有{}括号括住了一些值,为什么这么写呢,别急别急。其实这些{}号中的数据,就是我们要填充的数据的地方。括号中的名称就是存贮值的变量,好,要怎么填呢?
若我们从服务器上取到的JSON如下:

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
{  
“total”: “1”,
“page”: “1”,
“records”: “3”,
“rows”: [{
“groupname”: “美食图片”,
“mid”: 4766,
“sid”: 517,
“medianame”: “Tulips”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/0x6dvf.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673220000+0800)\/”,
“uploadtime”: “\/Date(1410673220000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 17.41
}, {
“groupname”: “美食图片”,
“mid”: 4765,
“sid”: 517,
“medianame”: “Penguins”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/6iluw6.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673215000+0800)\/”,
“uploadtime”: “\/Date(1410673215000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 15.62
}, {
“groupname”: “美食图片”,
“mid”: 4764,
“sid”: 517,
“medianame”: “Lighthouse”,
“mgid”: 549,
“mediatype”: “image”,
“mediaid”: “”,
“timestamp”: “”,
“localfile”: “/UploadFile/image/201409/14/fx0kzp.jpg”,
“picurl”: “”,
“thumbid”: “”,
“voiceformat”: “”,
“state”: 1,
“createtime”: “\/Date(1410673209000+0800)\/”,
“uploadtime”: “\/Date(1410673209000+0800)\/”,
“width”: 480,
“height”: 360,
“seizespace”: 14.2
}]
}

我们要填写到地方定义在下面Table中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$.ajax({  
url: ‘/manage/GetAllMediaListPage’,
type: ‘get’,
data: data,
cache: false,
dataType: “json”,
success: function(dta) {
if (!dta || !dta.rows || dta.rows.length <= 0) {
return;
}

//获取模板上的HTML
var html = $(‘script[type=”text/template”]’).html();
//定义一个数组,用来接收格式化合的数据
var arr = [];
//对数据进行遍历
$.each(dta.rows, function(i, o) {
//这里取到o就是上面rows数组中的值, formatTemplate是最开始定义的方法.
arr.push(formatTemplate(o, html));
});
//好了,最后把数组化成字符串,并添加到table中去。
$(‘#tableData’).append(arr.join(”));
//走完这一步其实就完成了,不会吧,这么简单,不错,就是这么简单!! 不信就自己动手去试试!
}
});

哟嚯,搞定,等等,好像表格的列数对不上,是吧,那是因为我没有把模板写完整出来,继续往下看。
现在我来解释为什么把模板代码放在<script></script>中间,假如,你把模板代码放在某个<div>中并隐藏起来,那么可能你的代码中会用到$(‘input[type=”text”]’)查找控件时,不好意思,就会把模板中的也统计进去了,这个并不是你想要的。所以我用<script>,这么做还有一个好处,就是不会被当成HTML来执行显示出来,但我们也得保证不能当成js来执行,所以加了个type=”text/template”,没有这个类型的,自己明白就好了。

另外,像o.mid的数值只会填充到{mid}这个里,不会填充到别的地方去,而且{mid}可以存在多个,一并全部替换成实际数值了。

接下来的一个问题就是,我取到的数据可能并不是我要给用户显示的,那么就需要变通一下了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var html = $(‘script[type=”text/template”]’).html();  
var arr = [];
$.each(dta.rows, function(i, o) {
//atime,asize和fsize这三个变量是之前的JSON中没有的,可灵活设置一下:
//格式化时间,当然getFormatDate这个函数我也公布出来了,格式化时间而已,见最后面。
o.atime = getFormatDate(o.uploadtime ? o.uploadtime : o.createtime, ‘yyyy-MM-dd’);
//图片的尺寸大小: 就是把上面的o.width和o.height变量组合一下,如果任何一个不存在,则返回”-“
o.asize = (o.width && o.height) ? o.width + ‘ * ‘ + o.height : ‘-‘;
//图片大小。存在才显示xxKB
o.fsize = o.seizespace ? o.seizespace + ‘&nbsp; KB’ : ‘-‘;
//格式化模板数据
arr.push(formatTemplate(o, html));
});
$(‘#tableData’).append(arr.join(”));

完整的HTML模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type=“text/template”>  
<tr mgid=“{mgid}” mid=“{mid}”>
<td>
<input type=“checkbox” mid=“{mid}”></td>
<td>
<a href=“{localfile}” data-fancybox-group=“button” class=“fancybox-buttons”>
<img src=“{localfile}” style=“width:45px;height:45px;”></a>
</td>
<td>
<input type=“text” class=“input-large valid” value=“{medianame}” onblur=“TextOnBlur(this)” onclick=“TextOnFocus(this)” name=“medianame” mid=“{mid}” readonly=“readonly”></td>
<td>{mediatype}</td>
<!– 各位看官,自定义的三个属性在这里哦~~ –>
<td>{fsize}</td>
<td>{asize}</td>
<td>{atime}</td>
<td>
<a onclick=“updateMediaName(this)” href=“javascript:void(0);”>重命名</a>
<a onclick=“showbulkUploadTemplate(this)” name=“edit” localfile=“{localfile}” href=“javascript:void(0);”>替换</a>
<a onclick=“daleteMedia(this)” href=“javascript:void(0);”>删除</a>
<a onclick=“setMediaFaceImage(this);” title=“设置为分组【{groupname}】的封面” groupname=“{groupname}” mid=“{mid}” href=“javascript:void(0);”>设置封面</a>
</td>
</tr>
</script>

其实想通了还是挺简单的,当然formatTemplate函数中的第一个参数必须要求是像struct的对象,直接一点就是这样一个数据包: { “A”: “a”, “B”: “b”, “C”:”c” } 。懂了吧伙计们,不懂就慢慢看吧,嘿嘿!

附: 格式化时间函数:

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
function getFormatDate(xdate, format) {  
try {
var format = format || ‘yyyy-MM-dd HH:mm:ss’;
var date = (xdate instanceof Date) ? xdate : new Date(parseInt(xdate.replace(‘/Date(‘, ”).replace(‘)/’, ”), 10));
var lang = {
‘M+’: date.getMonth() + 1,
‘d+’: date.getDate(),
‘H+’: date.getHours(),
‘m+’: date.getMinutes(),
‘s+’: date.getSeconds()
};
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1, (date.getFullYear() + ”).substr(4RegExp.$1.length));
}
for (var key in lang) {
if (new RegExp(‘(‘ + key + ‘)’).test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ?
lang[key] : (’00’ + lang[key]).substr((” + lang[key]).length));
}
}
return format;
} catch (e) {
return ‘-‘;
}
}