JavaScript模板引擎应用场景及实现原理详解
本文实例讲述了JavaScript模板引擎应用场景及实现原理。分享给大家供大家参考,具体如下:
一、应用场景
以下应用场景可以使用模板引擎:
1、如果你有动态ajax请求数据并需要封装成视图展现给用户,想要提高自己的工作效率。
2、如果你是拼串族或者数组push族,迫切的希望改变现有的书写方式。
3、如果你在页面布局中,存在共性模块和布局,你可以提取出公共模板,减少维护的数量。
二、实现原理
不同模板间实现原理大同小异,各有优缺,请按需选择,以下示例以artTemplate模板引擎来分析。
2.1模板存放
模板一般都是放置到textarea/input等表单控件,或者script[type="text/html"]等标签中,如下:
{{ifisAdmin}} {{title}}
{{eachuserasnamei}}
{{/if}} //textarea或input则取value,其它情况取innerHTML- {{i+1}}:{{name}}
{{/each}}
2.2模板函数
一般都是templateFun("id",data);其中id为存放模板字符串的元素id,data为需要装载的数据。
2.3模板获取
一般都是通过ID来获取,document.getElementById("ID"):
//textarea或input则取value,其它情况取innerHTML varhtml=/^(textarea|input)$/i.test(element.nodeName)?element.value:element.innerHTML;
2.4模板解析——处理html语句和逻辑语句及其他格式化处理
这步的主要操作其实多余的空格,解析出html元素和逻辑语句及关键字。例如:artTemplate.js中的代码实现:
defaults.parser=function(code,options){ //varmatch=code.match(/([\w\$]*)(\b.*)/); //varkey=match[1]; //varargs=match[2]; //varsplit=args.split(''); //split.shift(); //ifisAdmin code=code.replace(/^\s/,''); //["if","isAdmin"] varsplit=code.split(''); //if varkey=split.shift(); //isAdmin varargs=split.join(''); switch(key){ case'if': //if(isAdmin){ code='if('+args+'){'; break; case'else': if(split.shift()==='if'){ split='if('+split.join('')+')'; }else{ split=''; } code='}else'+split+'{'; break; case'/if': code='}'; break; case'each': varobject=split[0]||'$data'; varas=split[1]||'as'; varvalue=split[2]||'$value'; varindex=split[3]||'$index'; varparam=value+','+index; if(as!=='as'){ object='[]'; } code='$each('+object+',function('+param+'){'; break; case'/each': code='});'; break; case'echo': code='print('+args+');'; break; case'print': case'include': code=key+'('+split.join(',')+');'; break;
例如上例中:”{{ifisAdmin}}”最终被解析成”if(isAdmin){”,”{{/if}}“被解析成“}”。
2.5模板编译——字符串拼接成生成函数的过程
这步的主要操作就是字符串的拼接成生成函数,看看artTemplate的部分源码:
functioncompiler(source,options){ /* openTag:'<%',//逻辑语法开始标签 closeTag:'%>',//逻辑语法结束标签 escape:true,//是否编码输出变量的HTML字符 cache:true,//是否开启缓存(依赖options的filename字段) compress:false,//是否压缩输出 parser:null//自定义语法格式器@see:template-syntax.js */ vardebug=options.debug; varopenTag=options.openTag; varcloseTag=options.closeTag; varparser=options.parser; varcompress=options.compress; varescape=options.escape; varline=1; varuniq={$data:1,$filename:1,$utils:1,$helpers:1,$out:1,$line:1}; //isNewEngin在6-8返回undefined varisNewEngine=''.trim;//'__proto__'in{} varreplaces=isNewEngine ?["$out='';","$out+=",";","$out"] :["$out=[];","$out.push(",");","$out.join('')"]; varconcat=isNewEngine ?"$out+=text;return$out;" :"$out.push(text);"; varprint="function(){" +"vartext=''.concat.apply('',arguments);" +concat +"}"; varinclude="function(filename,data){" +"data=data||$data;" +"vartext=$utils.$include(filename,data,$filename);" +concat +"}"; varheaderCode="'usestrict';" +"var$utils=this,$helpers=$utils.$helpers," +(debug?"$line=0,":""); varmainCode=replaces[0]; varfooterCode="returnnewString("+replaces[3]+");" //html与逻辑语法分离 forEach(source.split(openTag),function(code){ code=code.split(closeTag); var$0=code[0]; var$1=code[1]; //code:[html] if(code.length===1){ mainCode+=html($0); //code:[logic,html] }else{ mainCode+=logic($0); if($1){ mainCode+=html($1); } } }); varcode=headerCode+mainCode+footerCode;
上例中模板中的模板字符串代码会被拼接成如下字符串:
'usestrict'; var$utils=this, $helpers=$utils.$helpers, isAdmin=$data.isAdmin, $escape=$utils.$escape, title=$data.title, $each=$utils.$each, user=$data.user, name=$data.name, i=$data.i, $out=''; if(isAdmin){ $out+='\n\n'; $out+=$escape(title); $out+='
\n
- \n';
$each(user,function(name,i){
$out+='\n
- '; $out+=$escape(i+1); $out+=':'; $out+=$escape(name); $out+=' \n'; }); $out+='\n
然后会被生成如下函数:
varRender=newFunction("$data","$filename",code); /*Outputs: functionanonymous($data,$filename){ 'usestrict'; var$utils=this, $helpers=$utils.$helpers, isAdmin=$data.isAdmin, $escape=$utils.$escape, title=$data.title, $each=$utils.$each, user=$data.user, name=$data.name, i=$data.i, $out=''; if(isAdmin){ $out+='\n\n'; $out+=$escape(title); $out+='
\n
- \n';
$each(user,function(name,i){
$out+='\n
- '; $out+=$escape(i+1); $out+=':'; $out+=$escape(name); $out+=' \n'; }); $out+='\n
2.5装载数据,视图呈现
/*Outputs:Userlists
- 1:zuojj
- 2:Benjamin
- 3:John
- 4:Rubby
- 5:Handy
- 6:CIMI
三、常见JavaScript模板引擎及测试对比
artTemplate——高性能JavaScript模板引擎(腾讯CDC)
Velocity.js——来自淘宝的JS模板引擎
JavaScriptTemplates——轻量、快速、强大、无依赖模板引擎
Juicer——高效、轻量的Javascript模板引擎
mustache.js——Logic-less{{mustache}}templateswithJavaScript
更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript查找算法技巧总结》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。