心血来潮,来写一个模板引擎吧!
功能就不多说了
实现思路
从最简单的开始吧
假设一个模板长这样
<h1><% var world = 'world!'; %> hello <%= world %></h1>
模板转化后应该到这样的:
1 2 3 4 5 6
| p += '<h1>'; var world = 'world!'; p += ' hello '; p += world; p += '</h1>';
|
总结一下这个过程,其实就只有三条规则:
%>...<%
转换为 %>p += '...';<%
, 起始和结束同此, 将内容直接作为输出<%...%>
转换为 ...;
, 逻辑处理, 直接执行<%=...%>
转换为 p += (...);
, 将运算结果作为输出
实现
实现就很简单了把上面的规则写成代码,
1 2 3 4
| tpl.replace(/(\s)+/g, " ") .replace(/(\%\>|^)(.+?)(\<\%|$)/g, "$1p += '$2';$3") .replace(/\<\%([^=](.(?!\<\%))+)\%\>/g, "$1;") .replace(/\<\%\=((.(?!\<\%))+)\%\>/g, "p += ($1);")
|
然后包装一下
1 2 3 4 5 6 7 8
| function render (tpl) { return new Function("data", "var p = ''; with(data){" + tpl.replace(/(\s)+/g, " ") .replace(/(\%\>|^)(.+?)(\<\%|$)/g, "$1p += '$2';$3") .replace(/\<\%([^=](.(?!\<\%))+)\%\>/g, "$1;") .replace(/\<\%\=((.(?!\<\%))+)\%\>/g, "p += ($1);") + "} return p; "); }
|
完成!
测试
1 2 3 4 5 6 7 8 9
| var tpl = `<ul> <% for (var i = 0; i < list.length; i++) { %> <li><%= list[i] %></li> <% } %> </ul>`; var renderFn = render(tpl); var renderResult = renderFn({list:["a", "b", "c", "d"]});
|
大功告成
当然中间还是遇到了很多问题,不过最终的结果还是非常好的,这个轮子项目已经放在github仓库