之所以使用模板引擎主要是为了避免麻烦的字符串拼接,同时,还用在重复的列表处理中。笔者自己开始就是因为要处理列表数据才接触的js模板引擎。而处理列表数据,自然是少不了 for 循环,而for循环对应的处理指令在很多模板中,都以 each 来标识。这里我们也用each.
通过前面几篇我们已经知道如何在模板中区分 代码内容和字符串内容,那在这里,我们只需要对 代码内容做进一步解析即可。
前面我们说了, 遇到 } 时, { 到 } 里的内容则被当作是 代码内容,那么我们只需要在遇到 } 那里对获取到的 代码内容做进一步处理。
//我们将改进这里,在push之前判断代码内容是否为each
case "}":
isvarcode = false;
resultcode.push(" result.push(" + varcode.join("") + ") ;");
varcode=[];
break;
模板代码:
<h3>{data.length}</h3><ul>{each}<li>{$index}:{$value}</li>{/each}</ul>
ps:$index $value 为循环体中指定的变量,处理时将会替换为对应的 下标 和 值
目标代码:
function func(data) {
var result=[];
result.push("<h3>") ;
result.push(data.length) ;
result.push("</h3><ul>") ;
for (var index in data) {
var value = data[index];
result.push("<li>") ;
result.push(index) ;
result.push(":") ;
result.push(value) ;
result.push("</li>") ;
}
return result.join("");
}
分析:
>从目标源码看,再结合我们前面已经实现的模板转换例子来看,我们这里不一样的地方就只有 {each}变成了 for (var index in data) { var value = data[index]; ,{/each} 变成了 } ,其它地方还是该代码内容还是原来的代码内容,原来push字符串内容的依旧是字符串内容。
>实际上,each的这个处理就是,遇到 each 那就说明这里是循环的开始,在这里只需要将 each 变成 for循环的开始部分, /each 当作是结束标识,遇到 /each 直接替换成 } 即可 (之后讲到的 /if 也是如此)。
>而模板中的 $index $value 将根据 for 循环中 具体使用的名称来替换,比如 $index 对应的是 for(var index in data) 中的 index,$value 对应的是 var value = data[index]; 中的 value,那么在模板中,若是遇到了 $index/$value 则将他们替换为对应的实际名称即可。
代码实现:
function Template2code(template) {
var resultcode = [];
resultcode.push("function func(data) { var result=[];");
var tempcode = [];
var varcode = [];
var isvarcode = false;
for (var key in template) {
var value = template[key];
switch (value) {
case "\"":
if (isvarcode) {
varcode.push("\\\"")
}
else {
tempcode.push("\\\"");
}
break;
case "{":
isvarcode = true;
resultcode.push(" result.push(\"" + tempcode.join("") + "\") ;");
tempcode=[];
break;
case "}":
isvarcode = false;
var varvalue = varcode.join("");
if(varvalue==="each")
{
resultcode.push("for (var index in data) {var value = data[index];");
}
else if(varvalue==="/each")
{
resultcode.push(" }");
}else{
varvalue = varvalue.replace("$index","index").replace("$value","value");
resultcode.push(" result.push(" + varvalue + ") ;");
}
varcode=[];
break;
default:
if (isvarcode) {
varcode.push(value)
}
else {
tempcode.push(value);
}
}
}
resultcode.push(" result.push(\"" + tempcode.join("") + "\") ;");
resultcode.push("return result.join(\"\");}")
return resultcode.join("");
}
生成方法:
var code = Template2code("<h3>{data.length}</h3><ul>{each}<li>{$index}:{$value}</li>{/each}</ul>");
document.getElementById("code").innerText = code;
var func = eval("(" + code + ")");
渲染的数据:
["11111","2222222","3333333333","4444444444"]
渲染结果:
<h3>4</h3><ul><li>0:11111</li><li>1:2222222</li><li>2:3333333333</li><li>3:4444444444</li></ul>
到了这里,我们已经可以基本使用each来循环我么的列表数据了。
但是,实际情况还要更复杂,比如我想多层嵌套,我还想在多层嵌套中的子层级引用父层级的内容,等等等等。。。
下一篇讲 each 的改进
目录: