继之前推出的70行代码实现的lua模版引擎后,又遇到了需要在js实现模版引擎的需求,遂实现之
首先是模版引擎的代码
var JTemplateEngine = function() {
var encodeAsString = function(s) {
return s.replace(/\\/g, '\\\\').replace(/'/g, '\\\'').replace(/\r/g, '\\r').replace(/\n/g, '\\n');
}
var compile = function(code) {
console.log(code);
// 输出缓冲
var outBuf;
// 仿php的echo函数,需要什么函数自己照着这个模式加就是了,项目中实际会有很多辅助函数
var echo = function(s) {
outBuf.push(s);
}
var __compiled;
eval('__compiled = function(params) { ' + code + ' }');
return function(params) {
outBuf = new Array();
__compiled(params);
return outBuf.join('');
}
}
var _class = function() { }
// 解析模版字符串并编译
_class.prototype.compile = function(template) {
var codes = new Array();
var buffer = new Array();
var state = 0;
for (i = 0; i <= template.length; i++) {
var c;
if (i == template.length) {
c = '\0';
} else {
c = template.charAt(i);
}
switch (state) {
case 0: // normal
if (c == '{') {
state = 1;
} else if (c == '\0') {
codes.push("echo('" + encodeAsString(buffer.join('')) + "');");
} else {
buffer.push(c);
}
break;
case 1: // perhapse inside
if (c == '%') {
codes.push("echo('" + encodeAsString(buffer.join('')) + "');");
buffer = new Array();
state = 2;
} else if (c == '\0') {
buffer.push('{');
codes.push("echo('" + encodeAsString(buffer.join('')) + "');");
} else {
buffer.push('{');
buffer.push(c);
state = 0;
}
break;
case 2: // inside
if (c == '%') {
state = 3;
} else if (c == '\0') {
codes.push(buffer.join(''));
} else {
buffer.push(c);
}
break;
case 3: // perhapse outside
if (c == '}') {
codes.push(buffer.join(''));
buffer = new Array();
state = 0;
} else if (c == '\0') {
buffer.push('%');
codes.push(buffer.join(''));
} else {
buffer.push('%');
buffer.push(c);
state = 2;
}
break;
default:
alert("bug");
}
}
return compile(codes.join('\n'));
}
return _class;
}();
接下来就用一个html页面来说明如何使用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>template test</title>
</head>
<body>
<div id="container"></div>
</body>
<script id="tmpl" type="text/html">
<style>
.t99 th, .t99 td { width: 30px; height: 30px; text-align: center;}
</style>
<table class="t99">
<tr>
<th></th>
{% for (var i = 1; i <= params.max; i++) { %}
<th>{% echo (i) %}</th>
{% } %}
</tr>
{% for (var i = 1; i <= params.max; i++) { %}
<tr>
<th>{% echo (i) %}</th>
{% for (var j = 1; j <= params.max; j++) { %}
<td>{% echo (i * j) %}</td>
{% } %}
</tr>
{% } %}
</table>
</script>
<script src="template.js"></script>
<script>
var jtmpl = new JTemplateEngine();
var tmpl1 = jtmpl.compile(document.getElementById('tmpl').innerHTML);
document.getElementById('container').innerHTML = tmpl1({max: 9});
</script>
</html>
运行结果
至于性能如何?个人项目中测试,需要渲染的页面重复生成十万次,只需要1秒多。