关键点
Function构造函数可以接收任意数量的参数,但是最后一个参数始终看成为函数体,前面的参数被看成返回的函数的参数
<body>
<div id="box">
My skills:
<%if(this.showSkills) {%>
<%for(var index in this.skills) {%>
<a href="#">
<%this.skills[index]%>
</a>
<%}%>
<%} else {%>
<p>none</p>
<%}%>
</div>
<script>
const box = document.getElementById('box')
{
const TemplateEngine = function (tpl, data) {
let re = /<%([^%>]+)?%>/g, code = 'let r=[];\n', cursor = 0;
var add = function (line, js) {
// js变量不应该push时带有引号
js ? code += `r.push(${line});\n` :
code += `r.push("${line.replace(/"/g, `\\"`)}");\n`;// 处理后=> r.push("<p>Hello, my n\"ame is ");
}
while (match = re.exec(tpl)) {
add(tpl.slice(cursor, match.index)); // 将匹配项之前的字符push进数组,即【<p>Hello, my name is 】push进去
add(match[1], true);// 将匹配到的变量push进去, 即【this.name】
cursor = match.index + match[0].length; // 移动截取下标
}
add(tpl.substr(cursor, tpl.length - cursor));// 将最后一段push进去,即【years old.</p>】
code += `return r.join("");`; // <-- return the result
console.log("code=>", code);
// Function构造函数可以接收任意数量的参数,但是最后一个参数始终看成为函数体,前面的参数被看成返回的函数的参数
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
}
var template = '<p>Hello, my n"ame is <%this.name%>. I\'m <%this.profile.age%> years old.</p>';
console.log("最终=>", TemplateEngine(template, {
name: "Krasimir Tsonev",
profile: { age: 29 }
}));
}
// 支持关键字
{
const TemplateEngine = function (html, options) {
let re = /<%([^%>]+)?%>/g, reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g, code = 'var r=[];\n', cursor = 0;
const add = function (line, js) {
js ? (code += line.match(reExp) ? line + '\n' : `r.push(${line});\n`) :
(code += line != '' ? `r.push("${line.replace(/"/g, `\\"`)}");\n` : '');
return add;
}
while (match = re.exec(html)) {
add(html.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(html.substr(cursor, html.length - cursor));
code += `return r.join("");`;
return new Function(code.replace(/[\r\t\n]/g, '')).apply(options);
}
// var template =
// 'My skills:' +
// '<%if(this.showSkills) {%>' +
// '<%for(var index in this.skills) {%>' +
// '<a href="#"><%this.skills[index]%></a>' +
// '<%}%>' +
// '<%} else {%>' +
// '<p>none</p>' +
// '<%}%>';
// 测试
let template = box.innerHTML.toString().replace(/</g, "<").replace(/>/g, ">")
let html = TemplateEngine(template, {
skills: ["js", "html", "css"],
showSkills: true
})
box.innerHTML = html
}
</script>
</body>
参考:博客1
原文地址:http://blog.jobbole.com/56689/