一个简单地template模板

本文介绍了一种简单的template模板引擎实现方法,通过自定义语法解析并生成JavaScript代码,支持基本的循环和条件判断,适用于前后端开发。

之前的项目中用到了artTemplate模板,感觉挺有意思,于是查看相关资料,自己动手写了个简单地template模板插件。虽然会有一些不足,但也是自己的一番心血。主体代码如下

 1        /*
 2         * 一个简单地template模板语法写法
 3         */
 4         !function () {
 5             "use strict";
 6             /*
 7              *tpl为传入的模板内容,data为数据
 8             */
 9             function template(tpl, data) {
10                 /*如果传入的是元素,则获取他的innerHTML赋值给他本身*/
11                 if (tpl.tagName) {
12                     tpl = tpl.innerHTML;
13                 }
14                 /*将tpl中的"转义*/
15                 tpl = tpl.replace(/"/g, '\\"');
16                 /*判断使用字符串拼接方式还是使用push方式*/
17                 var isTrim = ''.trim;
18                 /*定义正则表达式
19                 reg: 匹配分隔符<%%>
20                 reg1: 匹配原生js代码
21                 */
22                 var reg = /<%([^\n]*)%>/g;
23                 var reg1 = /(for|while|do|if|else|switch|case|default|break|continue|{|})/g;
24                 /*定义一个空数组的字符串*/
25                 var str = isTrim ? "var arr = [];" : ["var arr = [];"];
26                 /*定义一个初始的下标,下方会需要*/
27                 var index1 = 0;
28                 /*定义一个接收正则结果的变量*/
29                 var regResult;
30                 while (regResult = reg.exec(tpl)) {
31                     if (isTrim) {
32                         str += 'arr.push("' + tpl.slice(index1, regResult.index).replace(/\s+/g, ' ') + '");';
33                         if (regResult[1].match(reg1)) {
34                             str += regResult[1];
35                         } else {
36                             str += 'arr.push(' + regResult[1] + ');';
37                         }
38                     } else {
39                         str.push('arr.push("');
40                         str.push(tpl.slice(index1, regResult.index).replace(/\s+/g, ' '));
41                         str.push('");');
42                         if (regResult[1].match(reg1)) {
43                             str.push(regResult[1]);
44                         } else {
45                             str.push('arr.push(');
46                             str.push(regResult[1]);
47                             str.push(');');
48                         }
49                     }
50                     index1 = regResult.index + regResult[0].length;
51                 }
52                 if (index1 < tpl.length) {
53                     if (isTrim) {
54                         str += 'arr.push("' + tpl.slice(index1).replace(/\s+/g, ' ') + '");';
55                     } else {
56                         str.push('arr.push("');
57                         str.push(tpl.slice(index1).replace(/\s+/g, ' '));
58                         str.push('");');
59                     }
60                 }
61                 isTrim ? str += 'return arr.join("");' : str.push('return arr.join("");');
62                 isTrim ? '' : str = str.join('');
63                 return new Function(str).call(data);
64             }
65             window.template = template;
66         }();    

代码的逻辑很简单,通过isTrim判断是否采用字符串拼接的方法(字符串拼接在IE8一下浏览器中速度很是感人,所以一般采用数组的push方法);之后对获取到的tpl内容进行相关处理,处理成可供js执行的字符串,简单地例子如下:

<ul>
       <%for (var i = 0;i < data.arr.length;i++) {%>
         <li>
           <%for (var j = 0;j < data.arr[i].length;j++) {%>
                 <a href="javascript:void(0)" data_id="<%data.arr[i][j].id%>">
                  <%data.arr[i][j].name%>
                   <span>——</span>
                   <%data.arr[i][j].value%>
                   </a><br>
             <%}%>
             </li>
         <%}%>
</ul>

上述代码会被解析成如下字符串代码(在高版本浏览器下):

str = '<ul>';
for (var i = 0;i < data.arr.length;i++) {
    str += '<li>';
    for (var j = 0;j < data.arr[i][j].length;j++) {
        str += '<a href="javascript:void(0)"data_id="' + data.arr[i][j].id + '">' + data.arr[i][j].name + '<span>————</span>' + data.arr[i][j].value + '</a><br>';
    }
    str += '</li>';
}
str += '</ul>';

最终的字符串放在new Function()内执行(不是很了解这个方法的可以查看w3c,上面有详细的解释),生成需要的字符串。

(reg正则判断还是有问题,刚开始用的是 /<%([^%>]*)%>/g,但是这种匹配规则会不识别类似于<% if (a > b) {%>这种写法,但是有没有找到可以匹配<%开头、%>结尾、中间内容不存在%>的正则匹配规则,所以最终使用了 [^\n]代替,这样就必须每两个<%%>之间要有换行符隔开,但为了照顾到if判断中可能出现的>、<、%,也只好如此了。。。或许可以结合indexOf实现吧。。。)

 

一个简单地小demo如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
    <title>template</title>
    <script>
        /*
        * 一个简单地template模板语法写法
        */
        !function () {
            "use strict";
            /*
             *tpl为传入的模板内容,data为数据
            */
            function template(tpl, data) {
                /*如果传入的是元素,则获取他的innerHTML赋值给他本身*/
                if (tpl.tagName) {
                    tpl = tpl.innerHTML;
                }
                /*将tpl中的"转义*/
                tpl = tpl.replace(/"/g, '\\"');
                /*判断使用字符串拼接方式还是使用push方式*/
                var isTrim = ''.trim;
                /*定义正则表达式
                reg: 匹配分隔符<%%>
                reg1: 匹配原生js代码
                */
                var reg = /<%([^\n]*)%>/g;
                var reg1 = /(for|while|do|if|else|switch|case|default|break|continue|{|})/g;
                /*定义一个空数组的字符串*/
                var str = isTrim ? "var arr = [];" : ["var arr = [];"];
                /*定义一个初始的下标,下方会需要*/
                var index1 = 0;
                /*定义一个接收正则结果的变量*/
                var regResult;
                while (regResult = reg.exec(tpl)) {
                    if (isTrim) {
                        str += 'arr.push("' + tpl.slice(index1, regResult.index).replace(/\s+/g, ' ') + '");';
                        if (regResult[1].match(reg1)) {
                            str += regResult[1];
                        } else {
                            str += 'arr.push(' + regResult[1] + ');';
                        }
                    } else {
                        str.push('arr.push("');
                        str.push(tpl.slice(index1, regResult.index).replace(/\s+/g, ' '));
                        str.push('");');
                        if (regResult[1].match(reg1)) {
                            str.push(regResult[1]);
                        } else {
                            str.push('arr.push(');
                            str.push(regResult[1]);
                            str.push(');');
                        }
                    }
                    index1 = regResult.index + regResult[0].length;
                }
                if (index1 < tpl.length) {
                    if (isTrim) {
                        str += 'arr.push("' + tpl.slice(index1).replace(/\s+/g, ' ') + '");';
                    } else {
                        str.push('arr.push("');
                        str.push(tpl.slice(index1).replace(/\s+/g, ' '));
                        str.push('");');
                    }
                }
                isTrim ? str += 'return arr.join("");' : str.push('return arr.join("");');
                isTrim ? '' : str = str.join('');
                return new Function(str).call(data);
            }
            window.template = template;
        }();
    </script>
</head>

<body>
    <div id="app"></div>
    <script type="text/html" id="template">
        <h1>
            <%data.text%>
        </h1>
        <div>
            <%if (!data.arr) {%>
                <h3>数据暂时为空哦!</h3>
                <div>
                    <%}else{%>
                        <ul>
                            <%for (var i = 0;i < data.arr.length;i++) {%>
                                <li>
                                    <%for (var j = 0;j < data.arr[i].length;j++) {%>
                                        <a href="javascript:void(0)" data_id="<%data.arr[i][j].id%>">
                                            <%data.arr[i][j].name%>
                                            <span>——</span>
                                            <%data.arr[i][j].value%>
                                        </a><br>
                                        <%}%>
                                </li>
                                <%}%>
                        </ul>
                        <%}%>
                </div>
    </script>
    <script>
        var data = {
            text: "简单地template",
            arr: [
                [{ id: 1000, name: "葛小伦", value: "银河之力" }, { id: 1001, name: "刘闯", value: "长城一号" }, { id: 1002, name: "蕾娜", value: "太阳之光" }, { id: 1003, name: "赵信", value: "人生赢家啊" }],
                [{ id: 2000, name: "宋江", value: "及时雨" }, { id: 2001, name: "晁盖", value: "天王" }, { id: 2002, name: "林冲", value: "豹子头" }, { id: 2003, name: "武松", value: "行者" }],
                [{ id: 3000, name: "曹操", value: "丞相" }, { id: 3001, name: "关羽", value: "汉寿亭侯" }]
            ]
        };
        var html = template(document.getElementById('template').innerHTML, data);
        document.getElementById('app').innerHTML = html;
    </script>
</body>
</html>

 

转载于:https://www.cnblogs.com/cjs1992/p/7596606.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值