首页 关于我们

javascript模板

Word count: 453 / Reading time: 2 min
2016/06/08 Share

最早使用的js模板是这样子的

1
2
3
4
5
6
String.prototype.template = function(e, t) {
return this.replace(t || /\${([^{}]*)}/g, function(t, r) {
return e[r] !== undefined && e[r] !== null && e[r].toString() || ""
}
)
}

主要是通过正则来匹配,替换数据,不足之处是不能嵌入js的语句,对于一些需要遍历输出的就略显蛋疼了!想起underscore的template和ejs的模板,于是去看了一下它们的实现,主要原理还是:把不需要js的当作字符串,把需要js执行的直接用js执行,通过动态创建函数,执行模板。具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script type="text/template" id="tplStr">
<ul>
<% for(var i=0; i <users.length; i++) { %>
<li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
<% } %>
</ul>
</script>
function template(tplStr){
var result = "var _ary =[]; with(data){_ary.push('" + tplStr
.replace(/[\r|\s|\t]/ig, ' ')
.replace(/<%=(.*?)%>/g, "');_ary.push($1);_ary.push('")
.replace(/<%/g, "');")
.replace(/%>/g, ";_ary.push('")
+ "');}return _ary.join('')";

var fun = new Function("data", result);
return {
render: function(data){
console.log("by function: ", fun.apply(data, arguments));
}
}
}

步骤如下:

  1. 前面加上 var _ary =[]; with(data){_ary.push(‘

  2. <%=users[i].url%> 替换成’);_ary.push(users[i].url);_ary.push(‘

  3. <% 替换成 ‘);

  4. %> 替换成 ;_ary.push(‘

  5. 尾部加上’);}return _ary.join(‘’)

这里需要用with来暂时改变作用域链,以避免数据对象未知引起的错误,通过with可以忽略顶级的数据变量。最后通过apply来执行函数,可以使this指向当前的数据。

总的来说,难点在于如何把不变的当成字符串,需要就是执行的,让其直接执行。

CATALOG