之前的项目中用到了artTemplate模板,感觉挺有意思,于是查看相关资料,自己动手写了个简单地template模板插件。虽然会有一些不足,但也是自己的一番心血。主体代码如下
1 /* 2 * 一个简单地template模板语法写法 3 */ 4 !function () { 5 "use strict"; 6 /* 7 *tpl为传入的模板内容,data为数据 8 */ 9 function template(tpl, data) {10 /*如果传入的是元素,则获取他的innerHTML赋值给他本身*/11 if (tpl.tagName) {12 tpl = tpl.innerHTML;13 }14 /*将tpl中的"转义*/15 tpl = tpl.replace(/"/g, '\\"');16 /*判断使用字符串拼接方式还是使用push方式*/17 var isTrim = ''.trim;18 /*定义正则表达式19 reg: 匹配分隔符<%%>20 reg1: 匹配原生js代码21 */22 var reg = /<%([^\n]*)%>/g;23 var reg1 = /(for|while|do|if|else|switch|case|default|break|continue|{|})/g;24 /*定义一个空数组的字符串*/25 var str = isTrim ? "var arr = [];" : ["var arr = [];"];26 /*定义一个初始的下标,下方会需要*/27 var index1 = 0;28 /*定义一个接收正则结果的变量*/29 var regResult;30 while (regResult = reg.exec(tpl)) {31 if (isTrim) {32 str += 'arr.push("' + tpl.slice(index1, regResult.index).replace(/\s+/g, ' ') + '");';33 if (regResult[1].match(reg1)) {34 str += regResult[1];35 } else {36 str += 'arr.push(' + regResult[1] + ');';37 }38 } else {39 str.push('arr.push("');40 str.push(tpl.slice(index1, regResult.index).replace(/\s+/g, ' '));41 str.push('");');42 if (regResult[1].match(reg1)) {43 str.push(regResult[1]);44 } else {45 str.push('arr.push(');46 str.push(regResult[1]);47 str.push(');');48 }49 }50 index1 = regResult.index + regResult[0].length;51 }52 if (index1 < tpl.length) {53 if (isTrim) {54 str += 'arr.push("' + tpl.slice(index1).replace(/\s+/g, ' ') + '");';55 } else {56 str.push('arr.push("');57 str.push(tpl.slice(index1).replace(/\s+/g, ' '));58 str.push('");');59 }60 }61 isTrim ? str += 'return arr.join("");' : str.push('return arr.join("");');62 isTrim ? '' : str = str.join('');63 return new Function(str).call(data);64 }65 window.template = template;66 }();
代码的逻辑很简单,通过isTrim判断是否采用字符串拼接的方法(字符串拼接在IE8一下浏览器中速度很是感人,所以一般采用数组的push方法);之后对获取到的tpl内容进行相关处理,处理成可供js执行的字符串,简单地例子如下:
- <%for (var i = 0;i < data.arr.length;i++) {%>
- <%for (var j = 0;j < data.arr[i].length;j++) {%> <%data.arr[i][j].name%> —— <%data.arr[i][j].value%> <%}%> <%}%>
上述代码会被解析成如下字符串代码(在高版本浏览器下):
str = '
- ';for (var i = 0;i < data.arr.length;i++) { str += '
- '; for (var j = 0;j < data.arr[i][j].length;j++) { str += '' + data.arr[i][j].name + '————' + data.arr[i][j].value + ''; } str += ' ';}str += '
最终的字符串放在new Function()内执行(不是很了解这个方法的可以查看w3c,上面有详细的解释),生成需要的字符串。
(reg正则判断还是有问题,刚开始用的是 /<%([^%>]*)%>/g,但是这种匹配规则会不识别类似于<% if (a > b) {%>这种写法,但是有没有找到可以匹配<%开头、%>结尾、中间内容不存在%>的正则匹配规则,所以最终使用了 [^\n]代替,这样就必须每两个<%%>之间要有换行符隔开,但为了照顾到if判断中可能出现的>、<、%,也只好如此了。。。或许可以结合indexOf实现吧。。。)
一个简单地小demo如下
template