一步一步实现一个Javascript模板引擎(二)

上一篇文章实现了一个简单的js模板引擎,但当时我们只是考虑了模板中的输出,没考虑模板中的js逻辑,下面我们来处理模板中的js逻辑问题。我们来处理一个复杂的模板,模板代码如下:

<script type="text/tmpl" id="template">
    <p><strong>Name:</strong> <%= this.name %></p>
    <p><strong>Age:</strong> <%= this.age %></p>
    <% if (this.gender) { %>
        <p><strong>Gender:</strong> <%= this.gender %></p>
    <% } %>
    <% if (this.children) { %>
        <p><strong>Children:</strong></p>
        <% for (var i = 0, len = this.children.length, child; i < len; i++) { 
            child = this.children[i]; 
        %>
            <ul style="background-color: #f5f5f5;">
                <li><strong>Name:</strong> <%= child.name %></li>
                <li><strong>Age:</strong> <%= child.age %></li>
                <% if (child.gender == "female") { %>
                    <li><strong>Gender:</strong> <%= child.gender %></li>
                <% } %>
            </ul>
        <% } %>
    <% } %>
</script>

以上模板中包含了较多的js逻辑代码,看起来很复杂,不好解析,其实不然,原理还是一样的,使用正则表达式替换,功能增强后的模板引擎代码如下:

var guiTemplate = (function () {
    function template(tmpl, data) {
        var funcBody = 'var result = "";',
            func;

        tmpl = tmpl.replace(/\r|\n/g, "").replace(/"/g, '\\"'); //转义"号
        funcBody += ' result += "' + tmpl + '";'; 
        funcBody = funcBody.replace(/<%=\s*([^>]*)\s*%>/g, function(match, $1) {
            return '" + ' + $1.replace(/\\"/g, '"') + ' + "'; //替换的同时,恢复<%=%>中被转义的"号
        });
        funcBody = funcBody.replace(/<%\s*([^>]*)\s*%>/g, function(match, $1) {
            return '";' + $1.replace(/\\"/g, '"') + 'result += "'; //替换的同时,恢复<%=%>中被转义的"号
        });

        funcBody += " return result;";

        func = new Function(funcBody);
        return func.call(data);
    }
    return {
      template: template
    };
})();

调用代码如下:

var template = document.getElementById("template").innerHTML,
    html = guiTemplate.template(template, {
        name: 'guoyao',
        age: 26,
        gender: 'male',
        children: [
            {
                name: 'child 1',
                age: 5,
                gender: 'female'
            },
            {
                name: 'child 2',
                age: 3,
                gender: 'male'
            }
        ]
    });

生成的html如下:

<p><strong>Name:</strong> guoyao</p>        
<p><strong>Age:</strong> 26</p>                    
<p><strong>Gender:</strong> male</p>                            
<p><strong>Children:</strong></p>                            
<ul style="background-color: #f5f5f5;">                    
    <li><strong>Name:</strong> child 1</li>                    
    <li><strong>Age:</strong> 5</li>                                            
    <li><strong>Gender:</strong> female</li>                                    
</ul>                            
<ul style="background-color: #f5f5f5;">                    
    <li><strong>Name:</strong> child 2</li>                    
    <li><strong>Age:</strong> 3</li>                                    
</ul>

本文我们基本上实现了一个比较完整的js模板引擎,当然跟目前流行的开源模板引擎比较起来,我们的还不够完善,有空的时候我会继续完善它,不久将开源在Gitbub上,有兴趣的可以关注一下。

留下评论