一、前言

说起前端模板引擎,那可真是多如牛毛,只要是前端coder,怎么着你都听说或用过几款,社区里面的文章也有介绍,或者问问度娘,这里不再赘述。其中比较知名的有 artTemplate、doT、mustache等。

本文介绍两款极简模板引擎:一款原创format引擎,一款优化template引擎。每个模板引擎都只有区区三十行左右的代码。

二、模板原则

模板概念的提出,不管起源是什么,最根本的原则一定是要解决开发中的问题:显示逻辑和数据逻辑能够分离。而实际开发需求中,两者分离的需求也不尽相同。

三、实际问题

在实际开发中,我们很多时候就是以下几种模板格式化需求:

1、将一堆数据直接塞到模板字符串中,源数据很多的时候是对象,保不齐也需要是数组或者多参;

2、偶尔用一下模板中的循环逻辑、判断逻辑;

3、如果太复杂,就干脆load一段json然后配合一个函数来处理了,复杂度和可维护性往往是冲突的;

四、战术匕首

先看第一个需求:直接将数据塞入到字符串中。

如果撇开前端模板不谈,你会用什么方法?很显然,在 js 中处理字符串最为得心应手的莫过于正则表达式,一个简单的 replace 函数就可以完成查询和替换的工作:

1 var str = "<div>我是一个{name}</div>";
2 var data = {name:"测试用例"};
3 var ret = str.replace(/\{(\w+)\}/g, function(match, index) {
4     return data[index] || match;
5 });
6 console.log(ret)

上面这段代码足够简单,但是思路却是非常赞,使用js内置的正则引擎来高效处理字符串替换。而这个工作其实就是“模板引擎”的本职工作。

考虑数据源多样性、正则表达式预编译等需求,最终完善成以下本文要介绍的原创format引擎:

(function($, undefined) {//测试浏览器是否支持正则表达式预编译var baseReg = /\{([\w\.]+)\}/g, numReg = /^\d+$/,//预编译核心的正则表达式,以提高正则匹配效率formatReg = baseReg.compile ? baseReg.compile(baseReg.source, "g") || baseReg : baseReg,//其他工具函数toString = Object.prototype.toString, slice = Array.prototype.slice;//对外接口$.format = function(string, source){if( source === undefined || source === null )return string;var isArray = true, type = toString.call(source),//检测数据源data = type === "[object Object]" ? (isArray = false, source) : type === "[object Array]" ? source : slice.call(arguments, 1),N = isArray ? data.length : 0;//执行替换return String(string).replace(formatReg, function(match, index) {var isNumber = numReg.test(index), n, fnPath, val;if( isNumber && isArray ){n = parseInt(index, 10);return n < N ? data[n] : match;}else{ //数据源为对象,则遍历逐级查找数据fnPath = index.split(".");val = data;for(var i=0; i<fnPath.length; i++)val = val[fnPath[i]];return val === undefined ? match : val;}});};
})(window.jQuery || window.Zepto || window);

如果拿一个武器来比喻的话,我觉得战术匕首很适合:短小精悍,使用顺手。

这把刀是这样用的:

//模板内置到js中
var tmpl = ['<div>','这里是一个{name}','这里是其他元素',
'</div>'].join("");
var ret = $.format(tmpl, data);//从页面元素中获取模板
var tmpl = $("#tmpl")[0].innerHTML;
var ret = $.format(tmpl, data);

以上引擎能解决实际开发中多数的模板需求了,但是在有些时候,数据结构比较复杂,有循环、判断等逻辑在内,这个场景下,format就力不从心了。

五、沙漠之鹰

jQuery的作者John Resig的一个Micro-Templating非常合我胃口,不足三十行的代码,完成了上述含有逻辑处理的模板引擎,如果说format是一把前端开发中的战术匕首的话,这个无疑是一只沙漠之鹰。不过,这只沙漠之鹰用起来不太顺手:

1、只有从页面读取的模板才能缓存,而且必须是id元素;

2、为了节约前缀数据名,使用with这个令我觉得不爽的语法;

3、识别标识符不能更换,因为有些模板会输出到 jsp 页面(请谅解我们项目的特殊性),<%%>跟jsp的标志混淆;

于是,动手优化了大神的代码,经过实践完善后的代码如下(中间完善的过程不再一一叙述):

(function($) {var tmplCache={}, fnCache={}, guid=0, toString = Object.prototype.toString, compile = function( tmpl, sp ){//默认分隔符var f = sp || "%",//动态创建函数,并增加数据源引用(data/my)fn = new Function("var p=[],my=this,data=my,print=function(){p.push.apply(p,arguments);};p.push('" +// Convert the template into pure JavaScript
                tmpl.replace(/[\r\t\n]/g, " ").split("<" + f).join("\t").replace(new RegExp("((^|" + f + ">)[^\\t]*)'", "g"), "$1\r").replace(new RegExp("\\t=(.*?)" + f + ">", "g"), "',$1,'").split("\t").join("');").split(f + ">").join("p.push('").split("\r").join("\\'") + "');return p.join('');");return fn;};//对外接口$.template = function(tmpl, data, sp) {sp = sp||"%";var fn = toString.call(tmpl) === "[object Function]" ? tmpl: !/\W/.test(tmpl) ? fnCache[tmpl+sp] = fnCache[tmpl+sp] || compile(document.getElementById(tmpl).innerHTML, sp): (function(){for(var id in tmplCache)if( tmplCache[id] === tmpl ) return fnCache[id];return (tmplCache[++guid] = tmpl, fnCache[guid] = compile(tmpl, sp));})();return data ? fn.call(data) : fn;};
})(window.jQuery || window.Zepto || window);

优化后的代码仅仅保留了最为核心的正则处理部分,同时增加以下特性:

1、任意模板均自动编译和缓存;

2、模板可以从js输入,也可以从页面id元素中获取;

3、支持自定义分隔符;

4、支持数据源别名;

因为最终模板会编译成一个函数,所以,js能干的事儿,模板中都可以干,同时语法上跟 jsp 的标志相似,有过类似开发经验的同学几乎没有任何学习成本,是的,这个引擎也仅仅三十行左右。

经过优化改造的引擎,趁手了,强大了,用起来才有沙漠之鹰的感觉:

这把枪的用法如下:

//模板内置到js中
var templ = "this is a <%=my.type%> <%=data.name%> too.";
var ret = $.template(templ, {name:"demo", type:"easy"});//从页面id元素中获取模板
var ret = $.template("tmpl", {name:"demo", type:"easy"});

更多用法,请移步这里。

六、语法和性能

模板引擎几乎都会自造模板语法,但是就开发习惯而言,当你看到以下模板的时候,不知道作为前端开发人员,你会不会糊涂:

<ul>{{ for (var val, i = 0, l = it.list.length; i < l; i ++) { }}{{ val = it.list; }}<li>用户: {{=val[i].user}}/ 网站:{{=val[i].site}}</li>
    {{ } }}
</ul>

所以,在性能和语法习惯上,我个人非常倾向于后者。而性能问题,在日常开发中,不会变态到循环 10000 次,每次有 100 条数据的情况吧?

这个引擎在性能上不占太多优势(IE下除外),但是极为精简的代码,可以让你感觉不到他的存在,完全可以放入全站js中,随时供您调遣和使用。

当然,如果你的需求远不止上述两个方面,你可以尝试使用其他模板引擎,当然,还是建议优先考虑开发习惯,然后参考性能、体积等因素综合考虑,其中 doT 是除了语法习惯有点别扭之外,性能和体积综合最为优秀的一款引擎。而企鹅公司的artTemplate在支持模板调试,并可以在node环境下使用,功能还是很强大的。

我用artTemplate的性能测试用例跑了一下,本文从这里开始到末尾均是性能测试截图。为了防止名称跟其他模板冲突,测试用例中,沙漠之鹰的名字换成了 mcTemplate。有兴趣的同学,可以到这里自己试验:

上图为 chrome下高频测试结果

上图为 chrome下低频测试结果

上图为 firefox下高频测试结果

上图为 firefox下低频测试结果

上图为 IE11 下高频测试结果

上图为 IE11 下低频测试结果

IE7 下无法执行高频测试,直接卡死。上图是IE7低频测试结果

IE6 下无法执行高频测试,直接卡死。上图是IE6低频测试结果

转载于:https://www.cnblogs.com/zjcn/p/4275816.html

沙漠之鹰和战术匕首--两款前端极简模板引擎相关推荐

  1. 小巧 linux 网页浏览器,冷门软件!几款干净极简浏览器,小巧强大、高效出众...

    原标题:冷门软件!几款干净极简浏览器,小巧强大.高效出众 1.夸克浏览器 夸克浏览器,UC出品的一款干净极简的手机浏览器. 没有新闻推送.没有天气挂件.没有游戏插件.没有购物频道.没有精准广告.只做最 ...

  2. vue+elementUI 后台管理极简模板

    vue+elementUI 后台管理极简模板 写在前面 此篇文章为一篇说明文档,不是教你从零构建一个后台管理系统,而是基于一个实际项目,已经搭建好了一个后台管理系统的基础框架,教你如何在此基础上快速开 ...

  3. 【JavsScript】推荐五款流行的JavaScript模板引擎

    摘要:Javascript模板引擎作为数据与界面分离工作中最重要一环,受到开发者广泛关注.本文通过开发实例解析五款流行模板引擎:Mustache.Underscore Templates.Embedd ...

  4. 常见php模板_几款常见的PHP模板引擎

    PHP是一种HTML内嵌式的在服务器端执行的脚本语言,所以大部分PHP开发出来的Web应用,初始的开发模板就是混合层的数据编程.虽然通过MVC设计模式可以把程序应用逻辑与网页呈现逻辑强制性分离,但也只 ...

  5. 全新二开PHP自适应极简多引擎搜索单页网站源码

    介绍: 一个极简的搜索页面,同时兼顾了网址导航功能. 本项目由https://github.com/616620131/Simple-Search-Page 二次开发,加入了全网资源聚合搜索框,并且包 ...

  6. micropython ota_物联网产品的首选方案——5款追求极简设计的ESP32-PICO-D4开发板

    在物联网大行其道的今天,谈到乐鑫的ESP32系列产品真可谓无人不知无人不晓,但说真的,其中最让我钟情的还是那款基于ESP32的变种,采用SiP封装.简单到极致的ESP32-PICO-D4,原因无它,主 ...

  7. Windows server远程桌面配置【只需两步的极简快速版】

    1.右键我的电脑,点击远程设置,按以下图片设置 2.关闭防火墙 3.登录 OK

  8. easyexcel根据模板写入_用 Vue+ElementUI 搭建后台管理极简模板

    本文由图雀社区成员 灿若星空[1] 写作而成,欢迎加入图雀社区,一起创作精彩的免费技术教程,予力编程行业发展. 写在前面 此篇文章为一篇说明文档,不是教你从零构建一个后台管理系统,而是基于一个实际项目 ...

  9. element ui 前台模板_用 Vue+ElementUI 搭建后台管理极简模板

    本文由图雀社区成员https://blog.csdn.net/crxk_​blog.csdn.net 写在前面 此篇文章为一篇说明文档,不是教你从零构建一个后台管理系统,而是基于一个实际项目,已经搭建 ...

最新文章

  1. Virtual PC 使用指南
  2. 如何迁移 Flink 任务到实时计算
  3. 阿里云深圳数据中心正式开放
  4. ubuntu下装java
  5. 【Datapump】expdp和impdp中parallel参数解释
  6. 【GIS导论】实验七 地图设计与输出
  7. 与虚拟机和linux的初次接触
  8. php斐波那契数列循环,两种php实现斐波那契数列的方法
  9. java开发spc分析软件,告诉你们什么才叫真的SPC软件?
  10. 游戏编辑器研发第一天,对比思考确定底层技术和从0开发场景编辑器原因
  11. 计算机一级B考试总结500字,期中考试总结与反思500
  12. 2022秋招笔试备考合集——银行篇(下)|智测优聘出品
  13. 团队展示——我说的都队
  14. 英特尔携手生态伙伴亮相InfoComm,赋能协作办公迈向智能时代
  15. latex 图 表格 标题居中
  16. 文件夹名称有英语如何翻译为中文重命名
  17. 设置网站 titile keyword 以及 descript
  18. 利用html 和css模仿必应搜索主页。(一)
  19. 一路两输入正与门SN74AHC1G08学习
  20. 计算机科学家帕斯卡,帕斯卡-世界上最伟大的科学家排行榜-天天排行网

热门文章

  1. 教学设计、教案与学案
  2. 解除Windows文件占用
  3. 冯小刚和周星驰与2005民间语文走势【ZZ】
  4. 简单使用 Accessibility 及 Android 适配 TalkBack,实现适老化和无障碍
  5. 处理加权排序类型问题的一般套路
  6. 智能合约开发以及调用过程的注意事项
  7. 极企办公路由安全版坚固防御破解工具
  8. 部分游戏开发工具(转载)
  9. ldconfig mysql_ldconfig详解
  10. IT忍者神龟之Java网络爬虫回顾