JavaScript模板引擎的改进
2012-09-29 11:47
417 查看
阅读本文章之前,请先阅读 两个灵活高效的javascript模板渲染函数 ,因为这是针对那个模板引擎的改进。
那个模板引擎实现原理里,在每次渲染数据之前,会先把html模板编译成一个js函数,然后遍历每条数据调用这个函数,就完成整个数据列表的渲染。
改进的思路是:把html模板“编译”一次之后,就缓存起来,下次再渲染这个模板的时候,直接使用编译过的函数,而不用再次编译模板。
改进的方案之一:
原理:用数组存放模板,即把html模板字符串封装进一个数组里,这个数组只有这个字符串元素。每次调用模板引擎的时候,模板引擎编译完html之后,会把编译后的函数替换这个数组里模板字符串。这样当再次调用模板引擎的时候,先判断这个模板数组里存放的是字符串还是函数,是字符串就编译模板,是函数就不用再次编译。
改进后的模板格式:
改进后的模板引擎:
改进的方案之二:
思路:把模板引擎写成一个类,用html模板字符串和混合函数初始化这个类,初始化类的时候把模板字符串编译成函数。这个类提供两个prototype方法:一个是重置混合函数的方法(估计用到的几率十分十分小),一个是渲染数据到模板的方法。
渲染模板的时候,就先初始化一个实例,这样渲染不同数据的时候,只用这个实例就行,而只有初始化这个实例的时候编译过一次模板,达到了我们的改进目的。
这个方案的具体代码自己写吧。
小结:我原本以为之前那篇博文里的模板引擎已是很好,没有可改进的地方,但随着见识的增长,总是会让你发现很多可以改进的点。如果想变得越来越专业,只有谦虚好学,多思考。
那个模板引擎实现原理里,在每次渲染数据之前,会先把html模板编译成一个js函数,然后遍历每条数据调用这个函数,就完成整个数据列表的渲染。
改进的思路是:把html模板“编译”一次之后,就缓存起来,下次再渲染这个模板的时候,直接使用编译过的函数,而不用再次编译模板。
改进的方案之一:
原理:用数组存放模板,即把html模板字符串封装进一个数组里,这个数组只有这个字符串元素。每次调用模板引擎的时候,模板引擎编译完html之后,会把编译后的函数替换这个数组里模板字符串。这样当再次调用模板引擎的时候,先判断这个模板数组里存放的是字符串还是函数,是字符串就编译模板,是函数就不用再次编译。
改进后的模板格式:
//改进前的模板,就是一个字符串 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 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>'];为什么要从字符串换成数组,这是因为用字符串去调用一个函数的时候,是传值调用,函数里无法改变原字符串的值,而用数组这种非基本类型的对象去调用函数,相当于传址调用,在函数里可以改变原数组的内容。这样才能把模板字符串调包成“编译”后的函数。
改进后的模板引擎:
N.template = function(tpl, arrData, mix){ if( !arrData || !arrData.length ){ return ''; } var ret = '', hasMix = typeof mix==='function', i, len, evaluate, datai, mixdata, k; if( typeof tpl[0] === 'function' ){ evaluate = tpl[0]; }else{ var tpls = tpl[0].replace(/[\r\n\t]/g,'').replace(/\'/g,"\\\'").split('{'), sous, source = "return '"+tpls[0]+"'"; for(i = 1, len = tpls.length; i<len; i++){ sous = tpls[i].split('}'); source = source +(sous[0].indexOf('$')===-1?"+$."+sous[0]: "+("+sous[0].replace(/\[|\]/g,"'")+")")+"+'"+sous[1]+"'"; } console.log(source); //只会输出一次 evaluate = tpl[0] = new Function('$', source); } for(i = 0, len = arrData.length; i<len; i++){ datai = arrData[i]; if(hasMix){ mixdata = mix(datai, i); for(k in mixdata){ datai[k] = mixdata[k]; } } ret += evaluate(datai); } console.log('ret now...'); //每次都会输出 return ret; };改进后的调用方式不变:
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} ]; N.template(tpl, datas, function(d,i){ return { abx: i&1, abc: d.ab+2 }; }); N.template(tpl, datas, function(d,i){ return { abx: i&1, abc: d.ab+2 }; });改进后,可以发现用同一个html模板多次渲染数据,只会编译一次模板。
改进的方案之二:
思路:把模板引擎写成一个类,用html模板字符串和混合函数初始化这个类,初始化类的时候把模板字符串编译成函数。这个类提供两个prototype方法:一个是重置混合函数的方法(估计用到的几率十分十分小),一个是渲染数据到模板的方法。
渲染模板的时候,就先初始化一个实例,这样渲染不同数据的时候,只用这个实例就行,而只有初始化这个实例的时候编译过一次模板,达到了我们的改进目的。
这个方案的具体代码自己写吧。
小结:我原本以为之前那篇博文里的模板引擎已是很好,没有可改进的地方,但随着见识的增长,总是会让你发现很多可以改进的点。如果想变得越来越专业,只有谦虚好学,多思考。
相关文章推荐
- Juicer – 一个Javascript模板引擎的实现和优化
- Javascript 语言的模板引擎:Mustache
- Javascript 语言的模板引擎:Mustache
- 高性能JavaScript模板引擎原理解析
- 各种JS模板引擎对比数据(高性能JavaScript模板引擎)
- opencart 3.0.0.0及mycncart2.0.0.0的重大改进之模板引擎
- Juicer – 一个Javascript模板引擎的实现和优化
- 各种JS模板引擎对比数据(高性能JavaScript模板引擎)
- doT.js——前端javascript模板引擎问题备忘录
- 对几种流行的Javascript模板引擎的测试对比
- 在javascriptl中使用表格模板引擎template.js简化开发
- javascript模板引擎 Arttemplate
- JavaScript模板引擎使用
- [转载]Juicer – 一个Javascript模板引擎的实现和优化
- javascript模板引擎的概述
- 高性能JavaScript模板引擎原理解析
- javascript 模板引擎:artTemplate-3.0
- [转]高性能JavaScript模板引擎原理解析
- 前端模板引擎artTemplate---高性能JavaScript模板引擎
- JavaScript模板引擎原理