模板引擎

本篇文章主要是对模板引擎的学习做一个总结。

  • 除了好玩,通常我们造一个东西出来总是拿来用的,那模板引擎能拿来干嘛?

首先我们来看一段代码

var html = ''

html += '

姓名:张三

' html += '

年龄:23

' $('body').html(html)

比较常见的html拼接对吧,如果要拼接的字符串模板是这样的

姓名: <%name%>. 年龄:<%age%>

然后要把<%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 =  "

Hello, my name is <%name%>. I\'m <%age%> years old.

" html = TemplateEngine(html,data) $('body').html(html)

运行正常,ok
但如果数据在复杂一点,比如

{
    name: "Krasimir Tsonev",
    profile: { age: 29 }
}

这时候身高和体重就是错误的了。
要获得对应的数据,通过applay修改函数作用域,就可以这样写:

var html ='

Hello, my name is <%this.name%>. I\'m <%this.profile.age%> years old.

'

这时候需要插入能够执行的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) {%>' + 
    '<%this.skills[index]%>' +
    '<%}%>' +
'<%} else {%>' +
    '

none

' + '<%}%>'; console.log(TemplateEngine(template, { skills: ["js", "html", "css"], showSkills: false }));

上面是一个可以完成较为复杂表达式的例子。

你可能感兴趣的:(模板引擎)