ajax项目中使用模板

  以前写过一个javascript模板,也是为了提高开发效率,相应的也会牺牲一些执行效率,当然这种模板的使用也是要看情况来定的,并不是任何情况下它都能显著的效果。我个人之应用在对页面上已有的html文档插入数据时才使用的,如果html也是动态创建的,完全可以使用innerHTML。以下是代码:

 

代码
// JavaScript Document
//
模板命名空间
var template = {
//获取子节点的方式
child: function(node) {
var arr = [];
if (node.hasChildNodes()) {
for (var i = 0, childs = node.childNodes; i < childs.length; i++) {
if (childs[i].nodeType == 1) arr.push(childs[i]);
}
return arr;
}
else return 0;
},
//获取数组直接插入内容的正则表达式
reg: function() {
return (/<!--{.*}-->/g)
},
//获取属性名称的正则表达式
regSub: function() {
return (/<!--{(.*?)}-->/g);
},
//插入方法data为json数据,name为命名的模板名称,tag为可选,用来加快查找速度
insert: function(data, name, tag) {
//如果模板传入的是名称而不是节点,开始进行节点查找
if (name.constructor == String) {
var node = document.getElementsByTagName(tag || "*")
, element;
for (var i = 0; i < node.length; i++) {
//查找到模板属性符合条件的节点
if (node[i].getAttribute("template") && node[i].getAttribute("template") === name) {
//找到并赋值
element = node[i];
break;
}
}
}
//如果传入的是已找到的模板节点,直接赋值
else element = name;
this.adapter(data, element);
},
//递归查找方法,对子节点进行过滤
recursiveSerach: function(data, element) {
//获取当前节点的所有子节点,进行是否还有模板循环的检查
var childs = this.child(element)
, subData;
//如果有子节点,进行遍历
if (childs.length != 0) {
for (var n = 0; n < childs.length; n++) {
//查找每个节点时候有模板属性,如果有
if (childs[n].getAttribute("template")) {
var tem = childs[n].getAttribute("template");
subData
= eval("data." + tem);
//对有循环模板属性的节点进行数据优先插入
template.insert(subData, childs[n]);
break;
}
//如果没有进行字节的递归查找
this.recursiveSerach(subData || data, childs[n]);
}
}
},
//判断当前传入的数据是否为数组形式的json数据
adapter: function(data, elem) {
//如果是数组形式,直接执行方法
if (Object.prototype.toString.apply(data) === "[object Array]") this.insertArray(data, elem);
//如果不是直接强制转换成数组并执行
else this.insertArray([data], elem);
},
//对数组形式的json数据进行遍历
insertArray: function(data, elem) {
//避免空数组传入,产生错误
if (data.length === 0) return;
//找到数组节点的父节点,以供今后复制插入使用
var parent = elem.parentNode
//要循环插入数据的节点集合
, child = [elem];
//根据json数据的数量实现节点复制和添加
for (var i = 1; i < data.length; i++) {
var cloned = elem.cloneNode(true)
parent.appendChild(cloned);
child.push(cloned);
}
//对每条复制出来的节点进行对应的数据插入
for (var n = 0; n < child.length; n++) {
//优先进行子模板的插入,以防属性名称重复的问题
this.recursiveSerach(data[n], child[n]);
//进行数据插入
this.changeElement(data[n], child[n]);
}
},
//数据插入方法
changeElement: function(subData, elem) {
//如果循环的每一条结果是一个对象
if (subData.constructor == Object) {
//进行数据替换
elem.innerHTML = elem.innerHTML.replace(this.regSub(), function(match, sub) {
var str;
//如果数据存在则返回替换后的数据,如果不存在,不替换内容
try {
str
= eval("subData." + sub);
if (str) return str;
else return match;
}
catch (e) {
return match;
}
})
}
else {
//如果不是对象,而是需要直接插入的内容,进行替换插入
elem.innerHTML = elem.innerHTML.replace(this.reg(), function() {
return subData;
})
}
}
}

下面是使用的案例:

 

代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script type="text/javascript" src="template.js"></script>
<script type="text/javascript">
var json=[{
name:
"张三",
sex:
"",
age:{value:
25},
message:{a:[
"第一条","第二条","第三条","第四条"]}
},{
name:
"李四",
sex:
"",
age:{value:
12},
message:{a:[
"第1条","第2条","第3条","第4条"]}
}]
window.onload
=function(){
template.insert(json,
"info","div");
}
</script>
</head>

<body>
<div template="info">
<div><span>姓名:</span><!--{name}--></div>
<div><span>性别:</span><!--{sex}--></div>
<div><span>年龄:</span><!--{age.value}--></div>
<div>留言:
<ul>
<li template="message.a"><!--{}--></li>
</ul>
</div>
</div>
</body>
</html>

使用方法如下:

  首先要为你准备插入数据的html文档的元素添加一个template属性,然后随便定义一个名称,我们暂且称呼这个名称为容器名,容器名是调用template.insert()方法时的一个重要参数。

  template.insert方法有3个参数template.insert(json数据,容器名,[添加了容器名元素的标签名称])

  第一个参是要插入的数据,一般是由服务器返回的json格式。第二个参数就是上面我们提到的那个template定义的属性。第三个参数是可选的,就是定义了template属性的那个元素的标签名,这个参数就是为了能加快查找速度。接着只要把json数据对应的键放到你要插入的位置就可以了。像这样

 

<div><span>姓名:</span><!--{name}--></div>

 

那个name位置插入的就是name:"张三"和name:"李四"那两条数据,我们也看到了上面的json数据时这样的 json=[{},{}]; 有两条数据需要插入,遇到这种情况代码会自动循环输出插入了template属性的html代码块,所以"张三"和"李四"都会被输出。

  正如上面提到的那样有循环体的地方我们都需要插入一个template属性,比如这里

message:{a:["第1条","第2条","第3条","第4条"]}

 

 

这里message下的a属性实际上也是一个循环体,那么就在html中要循环的地方这样设置

 

<li template="message.a"><!--{}--></li>

由于a的循环体内是纯数组,所以{}内为空就可以,还要注意的是这个li设置的template属性和最初设置的template属性不同的是,它不可以随意命名,而必须表明它在数据当中的位置,因为它在json数据当中的位置是[message.a[]],所以要这样写 template="message.a"

  第一次用可能会觉得繁琐,不太习惯,但用惯了会很快的,只要在html上设置好,其他的就不用管了,数据循环都是自动的。当然这样造成的后果就是行为层和结构层的耦合,但有时候考虑到开发效率,就要看自己平衡利弊了。还有一个问题就是ie下无法对table内使用这个模板,因为ie  table的innerHTML是只读的,而这个程序的核心就是对innerHTML进行操作。暂时还没去解决这个问题,希望这个模板能对大家有所帮助。

posted @ 2009-12-16 17:30  黄金小强  阅读(389)  评论(0编辑  收藏  举报