由于前阵时间在写NiuEditer的扩展功能(莫笑话,这是自己取的名字,这个JS模块是为了取代副文本编辑器且实现样式可定制) ,需要用到模板解析, 项目排期不紧,所以我花了些时间来慢慢研究,
最初是看了Qwrap js的源码, 给了我一些思路, qwrap的源码地址为:http://dev.qwrap.com/download/latest/apps/qwrap-debug.js?20131207 ,搜tmpl。
实现模板解析最大的难题就是 变量解析 ,和字符串拼接。
例: hello world {$title} 好 {$content} {for(var i in data)} 你好 {/for} ,里面有 title,cotnent,data,及for循环, "{$ }" 代表变量, "{for}"代表循环,{/for}代表循环结束, 而我如何得到正确的结果 ?
首先我们要将这段文本转化成一段可执行的代码字符串。 而用户最终要得到的结果字符串,我们用一个变量来保存起来,我暂且先命名为returns_html.
那么我将 {$title} 替换成 " + title + " , 将 {for(var i in data)}转化为 ";for(var i in data) { returns_html += " , 将{/for} 转化为 ";} returns_html +=",最后我得到的字符串为:
hello world "+ title+" 好" +content+ "";for(var i in data) { returns_html +="你好";} returns_html +="
这段字符串想要执行还差什么, 两边还差 双引号,除了双引号外, 还缺了returns_html的定义,赋值和返回, 加上它们:
var returns_html="hello world "+ title+" 好" +content+ "";for(var i in data) { returns_html +="你好";} returns_html +="";return returns_html;
现在这个字符串就能够去远行了,可还有变量解析的问题。 用户传过来的数据肯定一个json对象, 例:{title:"title",content:"content",data:[1,2,3,4]}
我暂且将用户传过来的数据赋值给$tpldata, 可如何将$tpldata打散传给他们呢, 我看了很多人解决的方案是将模板变量加上datas前缀,便 {$title} 替换成 $tpldata.title, 可我不想这样做, 因为变量很有可能出现在循环的小括号中,如(for(var i indata)) 中的data变量,你如何去识别data这是个变量呢 ?
若我能做到
new Function("title","content","data",' var returns_html="hello world "+ title+" 好" +content+ "";for(var i in data) { returns_html +="你好";} returns_html +=""') (title,content,data)
那么这个问题就解决了,
由于能力有限,若未表述清楚或有失误可以联系364368940.
帖出原代码:
(function(a){
a.tpl = {
render:function(html,$tpldata){
var arr = [
{"pattern" :/\"/g,"replace":'\\\\"' }, //过滤双引号
{"pattern" :/\\n/g,"replace":'' }, //
{"pattern" :/{(while[^}]*)}/g,"replace":'";$1{ returns_html +="' }, //while
{"pattern" :/{(for[^}]*)}/g,"replace":'";$1{ returns_html +="' }, //for
{"pattern": /{(if[^}]*)}/g,"replace": '";$1{ returns_html +="'}, //if
{"pattern": /{(else if[^}]*)}/g,"replace": '";$1{ returns_html +="'}, //else if
{"pattern": /({\/if})|({\/for})|({\/while})}/g, "replace": '";} returns_html +="'}, //结束
{"pattern": /{\$ ([^}}]*)}/g, "replace": '";$1;returns_html+="'}, //js {$ js}
{"pattern": /{\$([^} ]*)}/g, "replace": '"+$1+"'} //变量解析{$val}
],param=[],params=[];
for(var i = 0,n = arr.length;i<n;i++){
html = html.replace(arr[i]['pattern'],arr[i]['replace']);
}
html = 'var returns_html=""; returns_html += " ' +html+ '";return returns_html;';
//变量打散 ,再套一层new Function
for(var i in $tpldata){
if($tpldata.hasOwnProperty(i)){
param.push(i);
params.push("$tpldata['"+i+"']");
}
}
try{
return new Function("$tpldata",'return new Function("'+param.join('","')+'",\''+html.replace(/\'/g,"\\'")+'\')('+params.join(",")+')')($tpldata);
}catch(e){
console.log(e.message);
console.log(html);
return '';
}
}
}
})(window);