在平时编码中,经常要做拼接字符串的工作,如把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
实际上解决起来很简单,添加一行正则对转义符进行转义:
str.replace(/\\/g,
"\\\\"
)
二、它有时候无法正确区分第一个参数是ID还是模板。
假若页面模板ID带有下划线,如 tmpl-photo-thumb 它不会去查找这个名称的模板,会认为这传入的是原始模板直接编译输出。
原始模板与元素id最直观的区别就是是否含有空格,因此改动下正则表达式即可:
三、它内部还残有一处测试用的代码,可删除。
print=
function
(){p.push.apply(p,arguments);}
tmpl 效率的疑惑
直到前段时间看了百度mux一篇介绍 YayaTemplate 的软文,原文作者对各大流行的模板引擎进行了效率测试,最终得出 YayaTemplate 是最快的一个。 虽然测试结果 tmpl 不敌 YayaTemplate ,但也让我打消了对性能的顾虑,实际应用中与传统的字符串拼接差不多。它们只有进行超大规模的解析才会有较大的性能差距。(超大规模?javascript本身就不适合干这事。若哪天程序员一次性给浏览器插入上千条列表数据而其慢无比的时候,不用怀疑:问题出在了这个程序员身上,他不会爱惜用户的浏览器。)
若说到引擎效率排名问题,我倒不觉得这是不能是衡量模板引擎的首要标准,模板语法也是重要的一环,这时候 YayaTemplate 的模板语法就显得晦涩多了,它为了节省几个正则表达式而在模板语法上耍了小聪明。
先展示 YayaTemplate 的源码:
若把性能问题上升到一个“学术问题”的高度尝试去解决,为什么 tmpl 会比 YayaTemplate 慢?
语法解析?虽然 YayaTemplate 使用了一个新颖的 javascript 包裹 html 的方式作为模板语法,但最终都需要用正则表达式解析成标准的 javascript 语法,这里正则的效率不会有太大的差异,并且双方都使用了缓存机制确保只对原始模板仅进行一次解析。
数据转换?模板引擎会把数据最终以变量的形式保存在闭包中,以好让模板获取到。这里先对比下一下双方的变量声明机制:
YayaTemplate 使用传统传递参数的形式实现。它通过遍历数据对象,把对象的名值分离,然后分别把对象成员名称作为new Function的参数名(即变量名),然后使用函数的appley调用方式传给那些参数。
tmpl 则使用了javascript不常用的 with 语句实现。 实现方式很简洁,省去了var这个关键字。
tmpl 性能问题就出在 with 上面。javascript 提供的 with 语句,本意是想用来更快捷的访问对象的属性。不幸的是,with语句在语言中的存在,就严重影响了 javascript 引擎的速度,因为它阻止了变量名的词法作用域绑定。
优化 tmpl
tmpl 若去掉 with 语句,而改用传统的传参性能立即大提升,经过实测在24万条数据下 firefox 能提高 5 倍,chrome 2.4 倍,opera 1.84倍,safari 2.1倍,IE6 1.1倍,IE9 1.35倍,最终与 YayaTemplate 不分上下。
测试地址:http://www.planeart.cn/demo/tmpl/tmpl.html
tmpl 优化版最终代码:
模板引擎依赖 Function 构造器实现,它与 eval 一样提供了使用文本访问 javascript 解析引擎的方法,这也会让性能显著的降低,但此时 javascript 中已别无他法。
使用 Function 构造器还会对参数名称有所限制,所以导致数据成员命名必须与 javascript 变量名规范保持一致,否则会报错。好在这个错误可以在运行的时候立马被发现,而不会成为一颗地雷。
tmpl 使用小窍门
一、缓存优化。
tmpl 默认对嵌入到页面中的模板进行了缓存优化(即第一个参数为ID的时候),它只会对模板进行一次分析。若原始模板是直接传入到 tmpl 第一个参数中,且需要多次使用的话,建议用公用变量缓存起来,需要解析数据的时候再使用,以获得相同的优化效果。如:
// 生成模板缓存
var render = tmpl(listTmpl);
// 可多次调用模板
elem.innerHTML = render(data1);
elem.innerHTML = render(data2);
...
二、避免未定义的变量引起系统崩溃。
若模板中定义了一个变量输出,而且传入数据却少了这个项目就会出现变量未定义的错误,从而引起整个程序的崩溃。如果无法确保数据完整性,仍然有方法可以对对其成员进行探测。原版中暗含变量保存了原始传入的数据,即 obj ;而在我的升级版本中则是关键字 this,如:
<% if (this.dataName !== undefined) { %>
<%=dataName %>
<% } %>
三、调试模板。
由于模板引擎是用文本的调用的 javascript 引擎,调试工具无法定位到出错的行。在 升级版本 中你可以用调试工具输出编译好的模板缓存。例如调试这个模板:
<script id="tmpl" type="text/tmpl">
<ul>
<% for (var i = 0, l = list.length; i < l; i ++) { %>
<li><%=list[i].index%>. 用户: <%=list[i].user%>; 网站:<%=list[i].site%></li>
<% } %>
</ul>
输出缓存:
window.console(tmpl(
'tmpl'
).$);
日志结果:
"$1318348744541.push('
<ul> '); for (var i = 0, l = list.length; i < l; i ++) { $1318348744541.push('
<li>',list[i].index,'. 用户: ',list[i].user,'; 网站:',list[i].site,'</li>
'); } $1318348744541.push(' </ul>
');return $1318348744541"
现在你可以看到模板引擎编译好的javascript语句,可以对照这检查模板是否存在错误。($1318348744541是一个随机名称的临时数组,可忽略)
最后非常感谢 tmpl 原作者 与 YayaTemplate 作者的付出,正因为此我才有机会深入分析实现机制,解决问题并从中受益。独乐不如众乐,分享之。
分享到:
相关推荐
### JavaScript模版引擎-tmpl的Bug修复与性能优化分析 #### 概述 在Web开发中,模版引擎是处理动态内容的一种常用技术。通过模版引擎,开发者可以轻松地将JSON数据转换为HTML格式,使得代码更加清晰、易于维护。`...
综上所述,文档通过分析javascriptmicrotemplating(tmpl)和YayaTemplate这两种模板引擎的实现、bug修复、性能测试与语法设计,全面介绍了模板引擎在前端开发中的应用及其优化方法。开发者可根据项目的实际需求和...
这些文件通常包括PHP脚本(如`search.cgi`,`buglist.cgi`等)和可能涉及的模板文件(`.tmpl`),它们可能包含了对中文搜索功能的优化或修正。在解压后,需要将这些文件覆盖到Bugzilla的安装目录,以替换原有的文件...
人脸识别项目实战
内容概要:本文详细描述了一个完整的Web应用程序的开发过程。该项目主要采用了Hono作为服务器框架,Prisma作为ORM工具,JWT用于认证鉴权,以及一系列现代化的最佳实践确保系统的健壮性和安全性。项目初期构建了基础架构,并设置了必要的依赖和工具。在后端方面涵盖了公共API接口的设计、CRUD增删改查逻辑、用户认证和授权等功能。此外还特别关注到了API的安全保护,如输入输出的校验,跨站请求伪造CSRF的防范,XSS防御等措施;为确保代码的质量引入了代码检测(比如ESLint搭配Prettier),并建立了完善的测试框架以保障后续开发阶段的功能正确。对于可能出现的问题预先定义了一组规范化的异常响应,并提供OpenAPI文档以方便开发者理解和调用。数据存储层面上利用了关系型与非关系型数据库各自的特性,实现了数据的有效组织,最后提供了实用的脚本,可用于种子数据插入以及执行必要的初始化工作。 适合人群:面向具有一定JavaScript/TypeScript开发经验,尤其是Node.js后台服务搭建经验的中级程序员和技术团队。 使用场景及目标:这份材料非常适合那些需要快速建立安全高效的RES
【资源介绍】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,也可以作为小白实战演练和初期项目立项演示的重要参考借鉴资料。 3、本资源作为“学习资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研和多多调试实践。 掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip
手势识别项目实战
(参考GUI)MATLAB BP的交通标志系统.zip
人脸识别项目实战
内容概要:本文详细介绍了 C++ 函数的基础概念及其实战技巧。内容涵盖了函数的基本结构(定义、声明、调用)、多种参数传递方式(值传递、引用传递、指针传递),各类函数类型(无参无返、有参无返、无参有返、有参有返),以及高级特性(函数重载、函数模板、递归函数)。此外,通过实际案例展示了函数的应用,如统计数组元素频次和实现冒泡排序算法。最后,总结了C++函数的重要性及未来的拓展方向。 适合人群:有一定编程基础的程序员,特别是想要深入了解C++编程特性的开发人员。 使用场景及目标:① 学习C++中函数的定义与调用,掌握参数传递方式;② 掌握不同类型的C++函数及其应用场景;③ 深入理解函数重载、函数模板和递归函数的高级特性;④ 提升实际编程能力,通过实例强化所学知识。 其他说明:文章以循序渐进的方式讲解C++函数的相关知识点,并提供了实际编码练习帮助理解。阅读过程中应当边思考边实践,动手实验有助于更好地吸收知识点。
Comsol光学仿真模型:包括纳米球 柱 Mie散射多级分解 ,Comsol光学仿真模型; 纳米球; 柱; Mie散射; 多级分解,Comsol光学仿真模型:纳米结构Mie散射多级分解
永磁同步电机全速域控制高频方波注入法、滑模观测器法SMO、加权切矢量控制Simulink仿真模型 低速域采用高频方波注入法HF,高速域采用滑膜观测器法SMO,期间采用加权形式切 送前方法 1、零低速域,来用无数字滤波器高频方波注入法, 2.中高速域采用改进的SMO滑模观测器,来用的是sigmoid函数,PLL锁相环 3、转速过渡区域采用加权切法 该仿真各个部分清晰分明,仿真波形效果良好内附详细控制方法资料lunwen 带有参考文献和说明文档,仿真模型 ,核心关键词: 1. 永磁同步电机; 2. 全速域控制; 3. 高频方波注入法; 4. 滑模观测器法SMO; 5. 加权切换矢量控制; 6. Simulink仿真模型; 7. 零低速域控制; 8. 中高速域控制; 9. 转速过渡区域控制; 10. 仿真波形效果; 11. 详细控制方法资料; 12. 参考文献和说明文档。,永磁同步电机多域控制策略的仿真研究
基于蜣螂优化算法的无人机三维路径规划【23年新算法应用】可直接运行 Matlab语言 主要内容:读取地形数据,利用蜣螂算法DBO优化三维路径,目标函数为总路径最短,同时不能撞到障碍物,效果如图所示,包括迭代曲线图、三维路径图、二维平面图等等 ,基于蜣螂优化算法;无人机;三维路径规划;总路径最短;障碍物避免;Matlab语言;迭代曲线图;三维路径图;二维平面图,蜣螂算法优化无人机三维路径规划:实时避障、路径最短新应用
清华大学2024年研究生复试上机考试题.zip
南京理工大学研究生入学考试2011年复试上机试题
手势识别项目实战
这里是3501的内容,用于复习资料
异步电动机变压变频调速系统,包含六千多字的文档、框架图、Simulink仿真模型,电力拖动、电机控制仿真设计 仿真模型+报告 开关闭环对比仿真都有,资料如图所见如所得 ,异步电动机;变压变频调速系统;六千字文档;框架图;Simulink仿真模型;电力拖动;电机控制仿真设计;开闭环对比仿真;资料如图。,异步电机控制仿真系统:六千字详解与图解
人脸识别项目实战
手势识别项目实战