本版本增添了局部模板功能,并且允许主模板调用局部模板,局部模块调用局部模块,并去掉onsite变量,不再提供解析成毕的文档碎片给使用者。它使用双重缓存,一是缓存那些通过同步请求得到的文本而成的数组,一是整体解析完毕得到的模板函数。模板函数是通过数组元素拼凑动成解析而成的,这是大大提高了效率。不过由于新功能的加入,虽然动用了新的构筑算法也比不上v2的构筑速度了……

有人说不要使用<%与%>做界定符,这个问题我在v1版本已经提出过了,这些都是可以自定义的。本文的例子将演示一下如何使用Django的{{与}}风格。

最后隆重推介一下本版本的新功能。不过由于条件有限,无法演示。现在模板不单单是内嵌于页面的script标签之内,也可以放置在一个独立的文件之内,如html,ejs,text,随你起什么后缀名。这个文件将会用同步请求回来用于构筑模板函数。我们可以用使用url属性,或在模板中使用<%: /template/partail.ejs >实现。一般而言,url是用于主模板,而<%: url %>是用于局部模板。如果我们在配置对象中同时使用selector与url,selector的优先级是高于url的。

var data = dom.ejs({selector:"tmpl",url:"/template/aaa.html",left:"{{",right:"}}",json: {name:"司徒正美",blog:"ruby louvre"address:"异次元"}});

源码:


//司徒正美 javascript template - http://www.cnblogs.com/rubylouvre/ - MIT Licensed(function () {if(!String.prototype.trim){String.prototype.trim = function(){return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');}}var dom = {quote: function (str) {str = str.replace(/[\x00-\x1f\\]/g, function (chr) {var special = metaObject[chr];return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)});return '"' + str.replace(/"/g, '\\"') + '"';}},metaObject = {'\b': '\\b','\t': '\\t','\n': '\\n','\f': '\\f','\r': '\\r','\\': '\\\\'},startOfHTML = "\t__views.push(",endOfHTML = ");\n";(function(){//http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspxvar s = ["XMLHttpRequest","ActiveXObject('Msxml2.XMLHTTP.6.0')","ActiveXObject('Msxml2.XMLHTTP.3.0')","ActiveXObject('Msxml2.XMLHTTP')","ActiveXObject('Microsoft.XMLHTTP')"];if( eval("''+/*@cc_on"+" @_jscript_version@*/-0")*1 === 5.7 && location.protocol === "file:"){s.shift();}for(var i = 0 ,el;el=s[i++];){try{if(eval("new "+el)){dom.xhr = new Function( "return new "+el)break;}}catch(e){}}})();dom.partial = function(url){var xhr = dom.xhr();xhr.open("GET",url,false);xhr.setRequestHeader("If-Modified-Since","0");xhr.send(null);return xhr.responseText|| ""}dom.tmpl = function(str,rLeft,rRight,sRight){var arr = str.trim().split(rLeft),self = arguments.callee,buff = [],url,els,el,i = 0, n= arr.length;while (i<n) {els = arr[i++]; el = els.split(rRight);if(els.indexOf(sRight) !== -1){//这里不使用els.length === 2是为了避开IE的split bugswitch (el[0].charAt(0)) {case "#"://处理注释break;case "="://处理后台返回的变量(输出到页面的);buff.push(startOfHTML, el[0].substring(1), endOfHTML)break;case ":"://处理局部模板url = el[0].substring(1).trim();//缓存构筑函数的数组self[url] = self[url] || self.call(null,dom.partial(url),rLeft,rRight,sRight);buff = buff.concat(dom.tmpl[url] );break;default:buff.push(el[0], "\n");};el[1] &&  buff.push(startOfHTML, dom.quote.call(null,el[1]), endOfHTML);}else{buff.push(startOfHTML, dom.quote.call(null,el[0]), endOfHTML);}}return buff;}dom.ejs = function (obj) {var sLeft = obj.left || "%>",sRight = obj.right || "<%",rLeft = new RegExp("\\s*"+sLeft+"\\s*"),rRight = new RegExp("\\s*"+sRight+"\\s*"),buff = ["var __views = [];\n"],key = obj.selector || obj.url,str;if(obj.selector){var el = document.getElementById(key);if (!el) throw "找不到目标元素";str = el.text;}else{str =  dom.partial(key);if(!str) throw "目标文件不存在";}if(!dom.tmpl[key]){//缓存模板函数buff = buff.concat(dom.tmpl.call(null,str,rLeft,rRight,sRight));dom.tmpl[key] = new Function("json", "with(json){"+buff.join("") + '\t};return __views.join("");');}return dom.tmpl[key](obj.json || {});};window.dom = dom;})();

示例:

<!doctype html>
<html><head><meta charset="utf-8"/><meta content="IE=8" http-equiv="X-UA-Compatible"/><meta name="keywords" content="javascript模板 by 司徒正美" /><meta name="description" content="javascript模板 by 司徒正美" /><title>javascript模板 by 司徒正美</title></head><body><h1>javascript模板 by 司徒正美</h1><div id="tmplTC">这是容器</div><script id="tmpl" type="tmpl"><h2>{{=  name }}{{= name }}</h2>{{# 这是注释!!!!!!!!! }}<ul>{{ for(var i=0; i< uls.length; i++){ }}<li>{{=  uls[i] }}的名字是{{= name }}</li>{{  }  }}</ul>{{ var color = "color:red;" }}<p style="text-indent:2em;{{= color }} ">{{= address }}</p></script><script src="dom/ejs.js"></script&gt<script>window.onload = function(){var els = [];for(var i=0;i<1000;i++){els.push("第"+i+"个元素")}var a = new Datevar data = dom.ejs({selector:"tmpl",left:"{{",right:"}}",json: {name:"司徒正美",uls:els,address:"异次元"}});document.getElementById("tmplTC").innerHTML = data;alert( new Date-a)}</script></body>
</html>

<!doctype html> <html> <head> <meta charset="utf-8"/> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <meta name="keywords" content="javascript模板 by 司徒正美" /> <meta name="description" content="javascript模板 by 司徒正美" /> <title>javascript模板 by 司徒正美</title> </head> <body> <h1>javascript模板 by 司徒正美</h1> <div id="tmplTC">这是容器</div> <script id="tmpl" type="tmpl"> <h2>{{= name }}{{= name }}</h2> {{# 这是注释!!!!!!!!! }} <ul> {{ for(var i=0; i< uls.length; i++){ }} <li>{{= uls[i] }}的名字是{{= name }}</li> {{ } }} </ul> {{ var color = "color:red;" }} <p style="text-indent:2em;{{= color }} ">{{= address }}</p> </script> <script> (function () { if(!String.prototype.trim){ String.prototype.trim = function(str){ return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); } } var dom = { quote: function (str) { str = str.replace(/[\x00-\x1f\\]/g, function (chr) { var special = metaObject[chr]; return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4) }); return '"' + str.replace(/"/g, '\\"') + '"'; } }, metaObject = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' }, startOfHTML = "\t__views.push(", endOfHTML = ");\n"; (function(){ //http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx var s = ["XMLHttpRequest", "ActiveXObject('Msxml2.XMLHTTP.6.0')", "ActiveXObject('Msxml2.XMLHTTP.3.0')", "ActiveXObject('Msxml2.XMLHTTP')", "ActiveXObject('Microsoft.XMLHTTP')"]; if( eval("''+/*@cc_on"+" @_jscript_version@*/-0")*1 === 5.7 && location.protocol === "file:"){ s.shift(); } for(var i = 0 ,el;el=s[i++];){ try{ if(eval("new "+el)){ dom.xhr = new Function( "return new "+el) break; } }catch(e){} } })(); dom.partial = function(url){ var xhr = dom.xhr(); xhr.open("GET",url,false); xhr.setRequestHeader("If-Modified-Since","0"); xhr.send(null); return xhr.responseText|| "" } dom.tmpl = function(str,rLeft,rRight,sRight){ var arr = str.trim().split(rLeft),self = arguments.callee,buff = [],url,els,el,i = 0, n= arr.length; while (i<n) { els = arr[i++]; el = els.split(rRight); if(els.indexOf(sRight) !== -1){//这里不使用els.length === 2是为了避开IE的split bug switch (el[0].charAt(0)) { case "#"://处理注释 break; case "="://处理后台返回的变量(输出到页面的); buff.push(startOfHTML, el[0].substring(1), endOfHTML) break; case ":"://处理局部模板 url = el[0].substring(1).trim(); self[url] = self[url] || self.call(null,dom.partial(url),rLeft,rRight,sRight); buff = buff.concat(dom.tmpl[url] ); break; default: buff.push(el[0], "\n"); }; el[1] && buff.push(startOfHTML, dom.quote.call(null,el[1]), endOfHTML); }else{ buff.push(startOfHTML, dom.quote.call(null,el[0]), endOfHTML); } } return buff; } dom.ejs = function (obj) { var sLeft = obj.left || "%>", sRight = obj.right || "<%", rLeft = new RegExp("\\s*"+sLeft+"\\s*"), rRight = new RegExp("\\s*"+sRight+"\\s*"), buff = ["var __views = [];\n"], key = obj.selector || obj.url,str; if(obj.selector){ var el = document.getElementById(key); if (!el) throw "找不到目标元素"; str = el.text; }else{ str = dom.partial(key); if(!str) throw "目标文件不存在"; } if(!dom.tmpl[key]){//以选择器-->解析函数的形式缓存到dom.tmpl函数中 buff = buff.concat(dom.tmpl.call(null,str,rLeft,rRight,sRight)); dom.tmpl[key] = new Function("json", "with(json){"+buff.join("") + '\t};return __views.join("");'); } return dom.tmpl[key](obj.json || {}); }; window.dom = dom; })(); window.onload = function(){ var els = []; for(var i=0;i<1000;i++){ els.push("第"+i+"个元素") } var a = new Date var data = dom.ejs({ selector:"tmpl", left:"{{", right:"}}", json: { name:"司徒正美", uls:els, address:"异次元" } }); document.getElementById("tmplTC").innerHTML = data; alert( new Date-a) } </script> </body> </html>

运行代码

现在我有一个考量,就是随着模板规模的膨胀,里面可能夹杂着越来越多变量,我们就很难分辨得清那些后台传过的东西,那些是本地的临时变量,后台的需求一变更,后台的json数据也就要改动。这维护起来非常困难。因此我非常欣赏ruby的变量书写风格,从变量名就知它是实例变量,类变量,普通变量与常量,它还有符号这东西呢,我会v4版本加入重新加入@标识符的。

javascript模板系统 ejs v3相关推荐

  1. javascript 模板系统 ejs v1

    由于各种原因,被逼使用前台模板.看了一下其他JS模板库的实现,发现其原理并不难,遂决定重造轮子. 做一个前台模板,有如下几个问题需要考量: 模板是放置于哪里?是内嵌于HTML页面还是像JS文件那样独立 ...

  2. javascript 模板系统 ejs v2

    本版本主要是对原模板系统进行提速,去掉消耗巨大的辅助函数.本来想用它与John Resig的 Micro-Templating比较一下速度,发现对方无法处理复杂的模板,残念. //司徒正美 javas ...

  3. javascript 模板系统

    由于各种原因,被逼使用前台模板.看了一下其他JS模板库的实现,发现其原理并不难,遂决定重造轮子.使用ROR.erb风格.换言之,逻辑是写在"<%"与"%>&q ...

  4. javascript 模板系统 (转)

    由于各种原因,被逼使用前台模板.看了一下其他JS模板库的实现,发现其原理并不难,遂决定重造轮子.使用ROR.erb风格.换言之,逻辑是写在""之间,如果是注释,则用"&q ...

  5. 商会机构源码模板系统包含了信息管理、新闻管理、广告管理、系统管理等功能 v3.9

    内容目录 一.详细介绍 二.效果展示 1.部分代码 2.效果图展示 三.学习资料下载 一.详细介绍 XYCMS商会机构源码模板系统是以asp+access进行开发的商会网站源码,包含了信息管理.新闻管 ...

  6. 【nodejs笔记3】Express基本用法,和路由控制,和模板渲染ejs

    1. 路由控制的工作原理 //routes/index.js中的代码//访问主页时,调用ejs模板引擎,渲染index.ejs模板文件,生成静态页面,并显示在浏览器中.router.get('/', ...

  7. 13 款 JavaScript 模板引擎

    JavaScript 在生成各种页面内容时如果能结合一些模板技术,可以让逻辑和数据之间更加清晰,本文介绍 X 款 JavaScript 的模板引擎.(排名不分先后顺序) 1. Mustache 基于j ...

  8. Django基础---Web框架、URL路由、视图函数、模板系统

    文章目录 Django基础 Django基础---Web框架 MVC和MTV框架 MVC MTV Django下载与安装 基于Django实现一个简单的示例 get请求获取数据 post请求获取数据 ...

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

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

最新文章

  1. cookies java,java 中 Cookie的用法
  2. 测试插件-infinitest介绍
  3. java applet 文本框_Java Applet 文本框 TextField 小例 | 学步园
  4. app启动页自动跳转源码_关于移动端App启动页的策划方案
  5. 江苏通报“中通宠物盲盒”事件:已立案调查
  6. SRM 567 div2
  7. [LeetCode] Spiral Matrix II
  8. 【转】linux常用命令:find、grep
  9. 无人驾驶安全报告分析
  10. 3dmax打开错误html,Windows安装3dmax软件失败提示错误三种解决办法
  11. 腾讯计算机编程本科年薪,腾讯程序员年薪80万,却感慨:天花板太低,想放弃工作去读研!...
  12. Redis学习之lpush命令
  13. ELk日志分析系统搭建
  14. 机器学习中的范数规则化之L0、L1与L2范数
  15. 【sv】 assign force区别
  16. 百度ueditor上传图片时如何设置默认宽高度
  17. 如何将网易云音乐的歌单同步到spotify
  18. DB9公母头引脚定义以及连接
  19. 第二章____一元函数微分学
  20. linux安装无线打印机,Unraid 安装CUPS实现共享打印和无线打印

热门文章

  1. 【角点检测】 基于各向异性高斯方向导数滤波器实现图像角点检测附matlab代码
  2. 吞咽障碍评估数据收集
  3. 计算机音乐数字乐谱梦中的婚礼,梦中的婚礼右手数字简谱
  4. MTK启动无线热点的过程
  5. npm ERR! Unexpected token ‘.‘ 报错解决办法
  6. CentOS 下配置NTP时间服务器
  7. redis 基础+进阶
  8. 2021计算机四级 软件测试工程师 真题(含答案解析)
  9. java Statement类
  10. 美国“微信们”收钱吗?