本篇文章主要是对模板引擎的学习做一个总结。
- 除了好玩,通常我们造一个东西出来总是拿来用的,那模板引擎能拿来干嘛?
首先我们来看一段代码
var html = ''
html += '<p>姓名:张三</p>'
html += '<p>年龄:23</p>'
$('body').html(html)
比较常见的html拼接对吧,如果要拼接的字符串模板是这样的
<p>姓名: <%name%>. 年龄:<%age%> </p>
然后要把<%name%>,<%age%>替换成数据
{
name: "Krasimir",
age: 29
}
这时候是不是想到要造个函数来完成替换的工作,简单的理解,模板引擎就是干这个。
- 首先,我们需要先构造一个正则表达式,匹配到相应需要替换的字符串,然后用replace方法进行替换。
var TemplateEngine = function(tpl, data) {
var re = /<%([^%>]+)?%>/g, match;
while(match = re.exec(tpl)) {
tpl = tpl.replace(match[0], data[match[1]])
}
return tpl;
}
data = {
name: "Krasimir Tsonev",
age: 29
}
var html = "<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>"
html = TemplateEngine(html,data)
$('body').html(html)
运行正常,ok
但如果数据在复杂一点,比如
{
name: "Krasimir Tsonev",
profile: { age: 29 }
}
这时候身高和体重就是错误的了。
要获得对应的数据,通过applay修改函数作用域,就可以这样写:
var html ='<p>Hello, my name is <%this.name%>. I\'m <%this.profile.age%> years old.</p>'
这时候需要插入能够执行的js代码(this.name)
可以利用 new Function
var fn = new Function("arg", "console.log(arg + 1);");
fn(2); // 输出 3
字符串"console.log(arg + 1);"就需要执行的函数体
这样,我们就有了构造复杂的模板的条件
var TemplateEngine = function(tpl,data){
var re = /<%([^%>]+)?%>/g;
var reExp = /(if|for|else|switch|case|break|{|})(.*)?/g
var code = 'var r=[];\n'
var cursor = 0;
var add = function(line,js){
console.log(line)
if(js){
if(line.match(reExp)){
console.log(line.match(reExp))
code += line+ '\n'
}else{
code += 'r.push(' + line + ');\n'
}
}else{
code += 'r.push("' + line.replace(/"/g,'\\"') + '");\n'
}
}
//将传入的字符串以<%...%>分割,分别push进数组,其中<%...%>被替换成了match[1]
while(match = re.exec(tpl)){
// console.log(match)
add(tpl.slice(cursor,match.index))
add(match[1],true)
cursor = match.index + match[0].length
}
//match=null时不执行while循环体,因而最后一个<%...%>后面的字符串没push进数组。
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 template =
'My skills:' +
'<%if(this.showSkills) {%>' +
'<%for(var index in this.skills) {%>' +
'<a href="#"><%this.skills[index]%></a>' +
'<%}%>' +
'<%} else {%>' +
'<p>none</p>' +
'<%}%>';
console.log(TemplateEngine(template, {
skills: ["js", "html", "css"],
showSkills: false
}));
上面是一个可以完成较为复杂表达式的例子。