现在的模板引擎挺多的,语法也多样,像handlerbar.js, template.js, artTemplate等等,模板引擎流程如下:
模板 -> 输入到模板引擎 -> 生成函数 -> 把数据当成参数,执行该函数 -> 输出结果
简单的模板引擎实现原理基本是用正则匹配的,复杂点的可能会用AST。
以下是两个简单实现template引擎的例子:
template1: https://juejin.im/post/59663eaa6fb9a06ba73d4c35
// Template1
var tmpl = function(tpl, data) {
var re = /<%([^%>]+)?%>/g;
var reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g;
var match;
var cursor = 0;
code = 'var r=[];\n';
var add = function(line, js) {
js? code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n':
code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n';
}
while(match = re.exec(tpl)) {
add(tpl.slice(cursor, match.index));
add(match[1], true);
cursor = match.index + match[0].length;
}
add(tpl.substr(cursor, tpl.length - cursor));
code += 'return r.join("");';
// console.log(code);
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
}
使用:
var template1 = '<p>Hello, my name is <%this.name%>. I\'m <%this.profile.age%> years old.</p>';
var tpl1 = tmpl(template1, {
name: "Krasimir",
profile: {age: 29}
})
template2: https://johnresig.com/blog/javascript-micro-templating/
// Template2
(function() {
var cache = {};
this.tmpl = function tmpl(str, data) {
var fn = !/\W/.test(str) //字母数字下划线
? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML)
: new Function(
"obj",
"var p = [], print = function() {p.push.apply(p, arguments);};"
+ "with(obj){p.push('"
+ str.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
return data ? fn(data) : fn;
};
})();
use:
var tpl = (
` <div id= "item_tmpl">
<div id="<%=id%>" class="<%=(i % 2 == 1 ? 'even' : '')%>">
<div class="grid_1 alpha right">
<img class="righted" src="<%=profile_image_url%>"/>
</div>
</div>
<%for ( var i = 0; i < users.length; i++ ) { %>
<li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
<% }%>
</div>`
);
var dataObject = {
users: [{
url: 'https://baidu.com',
name: '百度'
}, {
url: 'https://google.com',
name: '谷歌'
}],
id: 1,
i: 6,
profile_image_url: 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png'
};
var div2 = document.createElement('div');
div2.innerHTML = tmpl(tpl, dataObject);
document.body.appendChild(div2);
Others:
http://www.alloyteam.com/2016/10/implement-a-simple-template-engine/
https://handlebarsjs.com/