4行代码实现js模板引擎
在平时编码中,经常要做拼接字符串的工作,如把json数据用HTML展示出来,以往字符串拼接与逻辑混在在一起会让代码晦涩不堪,加大了多人协作与维护的成本。而采用前端模板机制就能很好的解决这个问题。
精妙的 tmpl
前端模板类开源的不少,但最属 jQuery 作者 John Resig 开发的 “javascript micro templating” 最为精妙,寥寥几笔便实现了模板引擎核心功能。 它的介绍与使用方式请看作者博客:http://ejohn.org/blog/javascript-micro-templating/
麻雀虽小,五脏俱全,除了基本的数据附加外,还拥有缓存机制、逻辑支持。现在,若要我评出一个javascript 最节能的自定义函数排名,第一名是 $ 函数(document.getElementById 简版),而第二名就是 tmpl 了。
当然,它并非完美,我使用过程中发现了一些问题:
tmpl 美中不足
一、无法正确处理转义字符,如: tmpl('<%=name%>\\<%=id%> ', {name:'糖饼', id: '1987'});它就会报错。若正常工作,它应该输出:糖饼\1987
二、无法识别数据里的单引号
三、设置变量默认值复杂,如
tmpl('<%if(obj.name){%><%=name%><%}else{%>默认值<%}%> ', {name:'糖饼'}); //设置name默认为 “默认值”
tmpl 优化版本
废话不多说,先敬上代码:
function tmpl(str, data) {
var $ = '$' + (+ new Date)
, fn = function (data) {
var i, variable = [$], value = [[]];
for (i in data) {
variable.push(i);
value.push(data[i]);
}
return (new Function(variable, fn.$))
.apply(data, value).join("");
}; //将模板解析成函数
fn.$ = fn.$ || $ + ".push('"
+ str.replace(/\\/g, "\\\\")
.replace(/'/g, "\\'") //防止单括号错误
.replace(/[\r\t\n]/g, " ")
.split("[:").join("\t")
.replace(/((^|:])[^\t]*)'/g, "$1\r")
.replace(/\t=([^\?]*?):]/g, "',$1,'")
.replace(/\t=([^\?]*?)\?(.*?):]/g, "',this.$1||'$2','") // [:=data?:] [:=data?任何内容:]
.split("\t").join("');")
.split(":]").join($ + ".push('")
.split("\r").join("\\'")
+ "');return " + $; //如果未定义data则返回编译好的函数,使用时直接传入数据即可,
//省去每次解析成函数的时间
return data ? fn(data) : fn; };
好吧,上面的代码看起来超出了4行,原谅我标题党。不过这段代码经过压缩后,确实只有四行^_^。下面我们就来详细解构它。
首先看一下使用示例:
//循环结构 var tpl = '[: for(var k in ary){ var one=ary[k]; :]'
+ '<p>[:=one:]</p>'
+ '[: } :]';
var data = {ary:[123,'abc']};
var div = tmpl(tpl,data);
console.log(div); //</p>123</p><p>abc</p> //变量验证 var tpl = '[: if(this.name!==undefined){ :]' //注意必须使用 this.name,直接使用name,如果未定义就会报错
+ '<p>[:=name:]</p>'
+ '[: } :]';
var data = {name:'abc'};
var div = tmpl(tpl,data);
//你还可以这样方便地使用未定义的变量:
var tpl = '<p>name:[:=name?:], name:[:=name?默认值:]</p>';
var data = {no:'abc'};
var div = tmpl(tpl,data); console.log(div); // <p>name:, name:默认值</p> //缓存编译结果 var tpl = '[: for(var k in ary){ var one=ary[k]; :]'
+ '<p>[:=one:]</p>'
+ '[: } :]';
var data = {ary:[123,'abc']};
var render = tmpl(tpl); //不传入data,则生成缓存,多次使用缓存节约大量正则运算
var div = render(data); //传入data,代入变量,解析成最终结果 console.log(div); //<p>123</p><p>abc</p>
使用方法:在 [: 与 :] 之间使用任何js代码,并且通过 [:=data:] 方式以字符串形式输出变量。更加详细的使用方法/手册,请查看:http://docs.codekart.jojoin.com/p/tool_tmpl
优化的地方:
一. 正确处理转义字符 \ ' 等转义字符
二. 修改包裹符 <% %> 为 [: :] 防止与 html标签</>和求余运算符%产生冲突。
三. 修改环境变量 obj 为 this
tmpl('<%if(obj.name=="name")%>') //旧版本
tmpl('[: if(this.name=="name") :]') //新版本
四. 为变量添加默认值
tmpl('<%if(obj.name){%><%=name%><%}else{%>默认值<%}%>') //旧版本
tmpl('[:=name?默认值:]') //新版本
五. 去掉 with 语句,大幅提升引擎性能
六. 删除可有可无的功能,保持精简
七. 增加调试模式
//打印模板编译中间结果:
console(tmpl('<p>[:=name:]</p>').$);
//$1408707567855.push('<p>',name,'</p>');return $1408707567855
此引擎函数大致分为两部分:
一. 上半部分:模板函数解析执行
二. 下半部分:正则运算生成模板函数
可以看出,引擎实现的重点主要在下半部分的一堆正则表达式,也就是“模板编译”的过程。这里我不打算把每一个正则的功能都说清楚,那样篇幅太大(好吧是我懒),各位看官请自行阅读研究。
另外,此模板引擎已被集成到 Node.js web开发框架 Codekart 中。
Codekart 是一套给 Node.js 开发者使用的应用程序开发框架和工具包。 它提供一套丰富的标准库以及简单的接口和逻辑结构, 其目的是使开发人员更快速地进行项目开发。 使用 Codekart 可以减少代码的编写量, 并将你的精力投入到项目的创造性开发上。
它已经帮你出色的完成了下面这些事情:
优雅的框架思维
如果你需要一个真正的框架,而不是一个模块/中间件/工具箱,如果你需要简约与便捷,需要一目了然、理所当然的舒适感,那么 Codekart 将是最好的选择。
高性能 HTTP 服务器
Codekart 处理 http 请求的性能接近原生 Node.js 代码: http.createServer(), 原因是框架只是对此函数做了简单的封装,其性能的损耗仅仅只有一个 url 正则匹配运算,路由请求处理程序。
便捷的静态文件服务器
把文件放入 static/ 目录下,启动Codekart,url 访问,搞定!
web 页面模块化支持
实际上,这是Codekart最出色的部分!它是前后端一体化的,可以像写配置文件一样编写web页面, 框架自动完成 js、css 、tpl 文件的模块化加载、合并、压缩, 并在html里引用,自动完成 html 模板的解析,并且支持页面继承和多态,一切就是那么简单轻松!
丰富的工具箱
Codekart 准备了一系列强大的前后端工具集合,涉及进程通信,数据缓存,文件读取,文件上传,数据采集与处理,流程控制,任务计划等诸多方面。
框架源码托管在Github:https://github.com/yangjiePro/Codekart 欢迎提交新的代码!
4行代码实现js模板引擎的更多相关文章
- doT js 模板引擎【初探】要优雅不要污
js中拼接html,总是感觉不够优雅,本着要优雅不要污,决定尝试js模板引擎. JavaScript 模板引擎 JavaScript 模板引擎作为数据与界面分离工作中最重要一环,越来越受开发者关注. ...
- js模板引擎介绍搜集
js模板引擎越来越多的得到应用,如今已经出现了几十种js模板引擎,国内各大互联网公司也都开发了自己的js模板引擎(淘宝的kissy template,腾讯的artTemplate,百度的baiduTe ...
- JS模板引擎:tppl
全球最快的JS模板引擎:tppl 废话不多说,先上测试: 亲测请访问:[在线测试地址]单次结果不一定准确,请多测几次. tppl 的编译渲染速度是著名的 jQuery 作者 John Resig 开发 ...
- JS模板引擎:基于字符串拼接
目的 编写一个基于字符串拼接的js模板引擎雏形,这里并不会提供任何模板与数据的绑定. 基本原理 Javascript中创建函数的方式有多种,包括: 1. var func = function () ...
- 使用新一代js模板引擎NornJ提升React.js开发体验
当前的前端世界中有很多著名的开源javascript模板引擎如Handlebars.Nunjucks.EJS等等,相信很多人对它们都并不陌生. js模板引擎的现状 通常来讲,这些js模板引擎项目都有一 ...
- JS 模板引擎 BaiduTemplate 和 ArtTemplate 对比及应用
最近做项目用了JS模板引擎渲染HTML,JS模板引擎是在去年做项目是了解到的,但一直没有用,只停留在了解层面,直到这次做项目才用到,JS模板引擎用了两个 BaiduTemplate 和 ArtTemp ...
- 掌握js模板引擎
最近要做一个小项目,不管是使用angularjs还是reactjs,都觉得大材小用了.其实我可能只需要引入一个jquery,但想到jquery对dom的操作,对于早已习惯了双向绑定模式的我,何尝不是一 ...
- 调研js模板引擎
js模板引擎越来越多的得到应用,如今已经出现了几十种js模板引擎,国内各大互联网公司也都开发了自己的js模板引擎(淘宝的kissy template,腾讯的artTemplate,百度的baiduTe ...
- Filter - Surge.js模板引擎过滤器
版权所有,转载请注明出处:http://guangboo.org/2014/01/05/filter-surgejs-template-engine 过滤器在surge.js模板引擎中多处用到,其类似 ...
随机推荐
- SVG图像技术摘要
该公司今天没有,研究了最近流行SVG技术,发现,随着css3不断流行,和浏览器技术的发展,SVG网站将取代大量的图片,成为主流站点图片展示. AI是我们经常使用的矢量图编辑器,如今AI能够直接另存SV ...
- java通过抛异常来返回提示信息
结论:如果把通过抛异常的方式得到提示信息,可以使用java.lang.Throwable中的构造函数: public Throwable(String message) { fillInStackTr ...
- 北京设计模式学习组bjdp.org第7次活动(2013.08.04)回顾会纪要
时间:2013.08.04,9am-7pm 地点:北京龙泉寺(北京凤凰岭风景区内) 参加人数:北京龙泉寺信息中心(20人).北京设计模式学习组(9人) 活动要点: 1)寺院巡礼:义工师兄带领参观寺院. ...
- cocos2d-x由Jni实现Java与C++打电话给对方
cocos2d-x由Jni实现Java与C++打电话给对方. cocos2d-x与开发商提供一个类JniHelper,提供java与c++之间的互jni解. 笔者所开发的"史上最坑爹的游戏& ...
- Mac下Jekyll安装
之前一直用Wordpress,虽然功能强大,各种插件各种bug,如果想弄个主题,折腾得要命.最近改用jekyll+gitHub免费空间.记录一下. 我用的是Mac,所以只讲述Mac下如何安装,Wind ...
- POJ 1026 Cipher(更换)
Cipher Time Limit: 1000MS Memory Li ...
- CSS3实现Tooltip提示框飞入飞出动画
原文:CSS3实现Tooltip提示框飞入飞出动画 我们见过很多利用背景图片制作的Tooltip提示框,但是缺点是扩展比较麻烦,要经常改动图片.还有就是利用多层CSS的叠加实现,但是效果比较生硬,外观 ...
- python派QQ邮件
#encoding=utf-8 __author__ = 'ds' #文件名冲突 from email.mime.text import MIMEText import smtplib if __na ...
- Scrapy研究和探索(五岁以下儿童)——爬行自己主动多页(抢别人博客所有文章)
首先.在教程(二)(http://blog.csdn.net/u012150179/article/details/32911511)中,研究的是爬取单个网页的方法.在教程(三)(http://blo ...
- C语言的这些事情有关内存
C语言的程序内存布局,从高到低依次为:栈区.堆区.未初始化数据区.初始化数据区.代码区. 一.栈区 由编译器自己主动管理,无需程序猿手工控制.存放函数的參数值.局部变量的值等.栈区内容从高地址到低地址 ...