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程序设计有所帮助。