Javascript:自己写模板引擎

背景

因为JS没有提供“字符串插入”和“多行字符串”特性,传统的拼凑字符串容易出错、性能不高和不容易理解代码,为了应对这些问题,很多个人和团队开发了模板引擎,现在主流的JS框架几乎都提供此类功能了。

模板引擎的实现方式有很多种,此处介绍一种简单、灵活和强大的思路,该方式借鉴了 JSP(web 服务器最终将 JSP 页面转换为了 Servlet),编译后会把模板转换为一个方法。

这个实现只是为团队介绍模板引擎的原理,具体应用还需要选择成熟的开源实现。

实现

 1 <!DOCTYPE html>
 2 
 3 <html xmlns="http://www.w3.org/1999/xhtml">
 4 <head runat="server">
 5     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 6     <title></title>
 7 </head>
 8 <body>
 9 </body>
10 </html>
11 <script id="test-tpl" type="text/template">
12 start
13 
14 <# for(var i=0; i< items.length; i++) {#>
15     <#= items[i].name #>
16 <# } #>
17 
18 end
19 </script>
20 <script type="text/javascript">
21     var Template = function (tpl) {
22         var me = this;
23 
24         me.tpl = tpl;
25     };
26 
27     Template.prototype.compile = function () {
28         var me = this;
29 
30         var codes = [];
31         codes.push("var results = [];");
32         codes.push("with(context) {");
33 
34         var frags = me.tpl.split(/(<#=.+?#>)|(<#.+?#>)/);
35         for (var i = 0; i < frags.length  ; i++) {
36             var frag = frags[i];
37 
38             if (!frag) {
39                 continue;
40             }
41             if (frag.indexOf("<#=") == 0) {
42                 codes.push("results.push(" + frag.substring(3, frag.length - 2) + ");");
43             }
44             else if (frag.indexOf("<#") == 0) {
45                 codes.push(frag.substring(2, frag.length - 2));
46             }
47             else {
48                 codes.push("results.push(‘" + frag.split(\n).join(\\n) + "‘);");
49             }
50         }
51 
52         codes.push("}");
53         codes.push("return results.join(‘‘);");
54 
55         console.log(codes.join("\n"));
56         me.compiledTplFun = new Function("context", codes.join("\n"));
57     };
58 
59     Template.prototype.apply = function (context) {
60         var me = this;
61 
62         if (!me.compiledTplFun) {
63             me.compile();
64         }
65 
66         return me.compiledTplFun(context);
67     };
68 
69     var tpl = new Template(document.getElementById("test-tpl").innerHTML)
70 
71     console.log(tpl.apply({ items: [{ name: "dgw" }] }));
72 </script>

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。