两个灵活高效的javascript模板渲染函数

为实现数据和展示分离,提高开发效率,方便维护,前端开发中通常需要用到渲染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(/[\r\n\t]/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(/[\r\n\t]/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语句,我估计效率低,谁测试一下看看。。。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值