概述
为实现数据和展示分离,提高开发效率,方便维护,前端开发中通常需要用到渲染HTML模板的函数。今天把自己写的两个“轻量级”的分享出来。
一、渲染一段简单的HTML模板
/**
* 简单的渲染模板的函数
* @method
* @param {String} tpl 待渲染的模板
* @param {Array | Object} data 渲染到模板里的数据
* @type String
* @example
N.tpl('<a target="_blank" href="http://blog.sina.com.cn/u/{0}">{1}</a>', [18277423, '苍老师的博客']);
//返回 '<a target="_blank" href="http://blog.sina.com.cn/u/18277423">苍老师的博客</a>'
N.tpl('<a target="_blank" href="http://blog.sina.com.cn/u/{uid}">{blogname}</a>', {
uid: 18277423,
blogname: '苍老师的博客'
});
//返回 '<a target="_blank" href="http://blog.sina.com.cn/u/18277423">苍老师的博客</a>'
*/
N.tpl = function(tpl, data){
return tpl.replace(/{(w+)}/g, function(all, match){
return data[match];
});
};
可以看出,它支持使用数组和对象格式的数据。其实在日常开发中,经常需要这么一个小小的函数,轻巧易用。
应该尽可能地避免使用拼接字符串那种形式来拼接数据和HTML串,那样开发效率低,不容易维护。
二、渲染数据列表
先来一个效率低的函数。
N.template0 = function(tpl, arrData, mix){
if( !arrData || !arrData.length ){
return '';
}
tpl = tpl.replace(/[rnt]/g, '');
var ret = '',
hasMix = mix!==undefined,
i = 0, len = arrData.length,
datai, mixdata, p,
rw = /{(w+)}/g, rS = /{=([^}]+)}/g;
var repw = function(all, match){
return datai[match];
};
var repS = function(all, match){
match = match.replace(/'/g, "\'").replace(/[|]/g, "'");
return (new Function('$', 'return '+match))(datai);
//try{return (new Function('$', 'return '+match))(datai)}catch(e){return ''}
};
for(; i<len; i++){
datai = arrData[i];
if(hasMix){
mixdata = mix(datai, i);
for(p in mixdata){
datai[p] = mixdata[p];
}
}
ret += tpl.replace(rS, repS).replace(rw, repw);
}
return ret;
};
这个使用正则匹配,对每一条数据都要用模板来进行一次匹配替换,性能太差。不做过多介绍,下面会给一个更快的函数,经简单测试知道在firefox和chrome下都要比前面这个快好几倍。
把这个写出来的目的,是想说其实在开发中,很多函数都可以不断地改进,只要你追求速度更快,性能更好。多思考一下就能做到。
N.template = function(tpl, arrData, mix){
if( !arrData || !arrData.length ){
return '';
}
tpl = tpl.replace(/[rnt]/g,'').replace(/'/g,"\'").split('{');
var ret = '',
hasMix = mix!==undefined,
i, len = tpl.length,
evaluate,
sous,
source = "return '"+tpl[0]+"'",
datai, mixdata, p;
for(i=1; i<len; i++){
sous = tpl[i].split('}');
source = source +(sous[0].indexOf('$')===-1?"+$."+sous[0]:
"+("+sous[0].replace(/[|]/g,"'")+")")+"+'"+sous[1]+"'";
}
//console.log(source);
evaluate = new Function('$', source);
for(i = 0, len = arrData.length; i<len; i++){
datai = arrData[i];
if(hasMix){
mixdata = mix(datai, i);
for(p in mixdata){
datai[p] = mixdata[p];
}
}
ret += evaluate(datai);
}
return ret;
};
主要思路就是先把模板解析成一个js函数,然后对每条数据执行这个函数生成一个渲染好数据的字符串,拼接所有字符串作为返回值。
参数说明:
tpl -- HTML模板;
arrData -- json数组格式的数据,必须是数组;
mix -- 混合函数,可选。传入该参数的话会以每条数据和数据对应的序号调用该函数,函数要返回一个json对象。把每条数据渲染到模板前,会把mix返回的json对象混入到每条数据里,这样在渲染模板时就可以使用这些数据。起到了改变数据的作用。
第一次写技术博客,不知道怎么讲明白,上例子吧,看例子更容易懂一些。
模板可以是两种形式,一种直接写在html文档里。如:
<script id="tpl" type="text/templete">
<div id="luck_box">
<div id="ava_list">
<div id="aa1023">{head}</div>
<div id="aa1023">{name}</div>
{$.abx ? [
<div id="aa10211"><img src="logo.jpg" />abxxxxxxxxxxxxxx</div>
<div id="aa10212"><img src="logo.jpg" /></div>]
: [
<div id="aa1024"><img src="logo.jpg" />no abx</div>
<div id="aa1025"><img src="logo.jpg" /></div>
]
}
</div>
</div>
</script>
一种是放在js代码里,如:
var tpl = '<li>'
+ '<div class="headPic"><a href="{domain}" title="{name}"><span></span></a>'
+ '<img alt="" src="{head}" width="60" height="60"/>'
+ '</div>'
+ '<div class="feedCon">'
+ '<span>{$.abx?[这是奇数行]+$.name:[偶的]}</span>'
+ '<span>{ $.abc===5 ? [是5] : [是]+$.abc }</span>'
+ '</div>'
+ '</li>';
数据例如:
var datas = [
{domain:'domainshit', name:'FLM', head:'headdffdddd',ab:3},
{domain:'dodshit', name:'FLMMjj', head:'he788ddd',ab:2},
{domain:'dode3errrrrtshit', name:'FL4MMjj', head:'he78y70008ddd',ab:5},
{domain:'dors2dshit', name:'FL3MMjj', head:'he78811ddd',ab:2},
{domain:'doma', name:'FffLM', head:'he2addd',ab:3}
];
混合函数例如:
function mix(d,i){
return {
abx: i&1,
abc: d.ab+2
};
}
mix函数提供了你改变数据,混入数据的功能,你要做什么复杂的数据处理也都放到mix函数里处理,然后将结果吐到返回的json对象里就行。
那么直接调用如:
//N.template(tpl, datas, mix);
N.template(document.getElementById('tpl').innerHTML, datas, mix);
三、使用规则
1、模板里直接输出数据用{}包起数据key就行了。
2、模板里可以执行简单的js代码,比如三目运算,当然也只建议使用三目,复杂的逻辑请写在混合函数里,而在模板里只调用数据。
若是执行js代码,引用数据需要使用$.name来使用数据中的name值,而这里面的字符串使用[]包括而不是单双引号,这样的好处不多说。。。
3、如果你要输出{和}这两个符号,那么你可以用混入数据来输出,但我估计你800年用不到一次。。。
几点特色:
1、不使用<%=name%>这种来区分变量,这种太麻烦,要多敲几个字符,直接{name}多省事,而且中英文下大括号{}是相同的。。。
2、引入混合函数,哇,你可以在这里面想做什么做什么,可以很有效地把逻辑代码和模板分离。
3、行业里比较流行的模板函数都用到了with语句,我估计效率低,谁测试一下看看。。。
最后
以上就是眼睛大康乃馨为你收集整理的两个灵活高效的javascript模板渲染函数的全部内容,希望文章能够帮你解决两个灵活高效的javascript模板渲染函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复