JavaScript设计前端模板初步理解
Posted 「已注销」
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计前端模板初步理解相关的知识,希望对你有一定的参考价值。
模板这个词,可能很多人第一印象是后端的技术(Smarty,Velocity等),但本文要讲的却不是后端的概念,而是前端开发中所使用到的一种技术,也就是“前端模板”技术。
模板的工作原理可以简单地分成两个步骤:模板解析(翻译)和数据渲染。这两个步骤可分别部署在前端或后端来执行。如果都放在后端执行,则是像Smarty这样的后端模板,而如果都放在前端来执行,则是我们要探讨的前端模板。
问题
随着前端交互的复杂性不变提升,无刷新页面数据传输与渲染越发地频繁化,我们发现传统的前端开发方式在ajax数据渲染等方面存在着一个主要问题:繁琐的数据渲染。当前端从后台通过ajax等方式或许到数据后,如果要将这个数据渲染到指定的dom元素中,则需要进行各种字符串拼接工作或者一系列创建元素的工作,还不论细节的问题(单引号双引号问题等),不管是哪一种形式,都是繁琐且费时的。同时,在可读性与维护性上也存在问题。试想,各种循环操作的字符串拼接,元素创建插入,在需要修改时,都需要重新花费不少时间与精力。那有什么方法可以解决这个问题呢?
原理
当我们在JSP中写ulli%= name %/li/ul的时候,其实就是在应用模板,在后台这句话会被转换成out.print(ulli+name+/li/ul)。模板的数据渲染就是把模板中的占位符(这里是name),替换成传入的值(比如替换成yaya)。而在前端开发中,这种方式依然具有很高实用价值。前端模板的核心是前端模板引擎,引擎将前端的模板语言转换成浏览器可以解析的html语言。当转换成功后,便可以很方便地将这段html代码放到我们希望的地方去。
比如我们可以写一段循环的li标签的前端模板语言。通过前端模板引擎转换后成为一连串li标签的html语言。这时候就可以直接采用innerHTML方法把html代码插入到ul对象中,那么就完成了生成ul列表的功能。
初识
前端的模板核心是模板解析引擎,而解析引擎的主要作用是将模板语言转换成html/xml格式。不同的前端模板有着不同的模板语言,解析引擎因此也各不相同。让我们先来认识几款前端模板,了解下它们各自的模板语言。
Yaya Template是一款轻量级的模板引擎,采用原生javascript语法,具有易学易用等特点。我们来看一段用Yaya Template渲染列表数据的实例:
模板语言(通用过for循环,输出这是第n列的li列表)
for ( var i = 0 ;i < list.length;i ++ )$ < li > 这是第 % i % 列: % list[i] % < / li> $
有了模板语言后,我们只需要将数据打入模板语言中的list,就可以生成我们想要的html/xml格式了。如上例,我们只需要得到这个模板语言进行翻译,并调用对应的render方法,
var list = [红桃,方块,梅花,黑桃];var html = YayaTemplate(templateText).render(list:list);
这个html则是模板引擎转换成的html/xml语言,在上例中,则为:
< li > 这是第0列:红桃 < / li>< li > 这是第1列:方块 < / li>
< li > 这是第2列:梅花 < / li>
< li > 这是第3列:黑桃 < / li>
从这个例子中,我们可以发现,$…$表示输出的html/xml片段,%…%表示输出javascript变量。得到的html,我们可以用直接作为dom的innerHTML或者其他用处。
这便是前端模板,它使得我们不必去处理字符串拼接等问题,用最直观的方式来渲染数据。我们再来看另外一款前端模板EasyTemplate。还是之前的例子,用EasyTemplate模板写法如下:
< #list data as list >< li > 这里是第$list_index 列:$list < / li>
< / #list>
同样,需要将实际数据替换模板变量,这里采用:
var list = [红桃,方块,梅花,黑桃];var html = easyTemplate.render(templateText,list); // templateText指模板语言
像EasyTemplate这样的前端模板,是属于自定义模板语言的一种前端模板。我们可以从上例看出,就是EasyTemplate自定义的循环条件。像这样EasyTemplate模板一样采用自定义标签的前端模板还有 lite Template:
< c: for var = item list = $list >< li > 这里是第$ for .index列:$item < / li>
< / c:for>
渲染时采用:
var list = [红桃,方块,梅花,黑桃];var html = liteFunction(templateText,’list’)(list);
好了,我们再来看看jquery作者John Resig所写的一个前端模板jquery template。说真的,它如同jquery一样,短小精悍。还是老例子:
<% for ( var i = 0 ;i < list.length;i ++ ) %>< li > 这是第 <%= i %> 列: <%= list[i] %>< / li>
<% %>
渲染采用:
var list = [红桃,方块,梅花,黑桃];var html = tmpl(templateid, list);
我们可以看出,Yaya Template与jquery template在模板语言的写法上正好相反。前者将输出html语言做特殊标记$…$,而后者对javascript语言做特殊标记。这两种模板已经使得学习成本很低了,而接下来介绍的ace template的写法将更加简单易懂。
for ( var i = 0 ;i < list.length;i ++ )< li > 这是第 # i 列:# list[i] < / li>
渲染采用:
var list = [红桃,方块,梅花,黑桃];var html = AceTemplate.format(templateid, list:list);
ace template采用了html与js语言直接混搭的风格,在两者间可以直接的书写,不用添加任何的标志用以区分不同的语言。而在html语言里面,使用js变量则采用#的方式输出。ace template之所以可以兼容html与js混合写法,是通过按行解析来实现的。所以,如果代码能够保证html语言与js按行划分,这样的用法其实是很方便的。并且ace template值得说明的一点是支持自动编码防止xss漏洞,通过#渲染出来的javascript变量,已经经过了编码处理,这一点是很方便的。而对于不需要这个功能,需要原文输出的时候,ace template也提供了!#方法来满足这种需求。
通过上面对五个前端模板的简单介绍,我们可以了解到不同前端模板的各种形态,这包括写法与用法等直观印象。但我们知道,前端模板的核心是代码的转换,这肯定是需要转换时间的,那就以上五个不同的前端模板,性能上会有怎样不同的表现呢。
性能
前端模板语言到html/xml语言,是通过模板引擎进行翻译的。而模板引擎的翻译性能在某种程度上决定了前端模板解决方案的可行性的高低。上诉五种前端模板,各自的性能会是怎么样的,我们对它们进行测试。分别对Yaya Template、EasyTemplate、jquery template、 ace template、lite template部署前端模板做同样的操作,比较模板引擎翻译时间代价。
各自的模板代码如下:
Yaya Templat
for (var i=0;i<list.length;i++)if (i<100)
$<li>小于100 这里是第%i% 列:%list[i]%</li>$
else
$<li>不小于100 这里是第%i% 列:%list[i]%</li>$
EasyTemplate
<#list data as list><#if (list_index <100)>
< li > 小于100 这里是第$list_index 列:$list < / li>
<#else>
< li > 不小于100 这里是第$list_index 列:$list < / li>
</#if>
</#list>
jquery template
<%for (var i=0;i<list.length;i++) %><%if (i<100) %>
< li > 小于100 这里是第 <%= i %> 列: <%= list[i] %>< / li>
<% else %>
< li > 不小于100 这里是第 <%= i %> 列: <%= list[i] %>< / li>
<% %>
<% %>
ace template
for (var i=0;i<list.length;i++)if (i<100)
< li > 小于100 这里是第#i 列:#list[i] < / li>
else
< li > 不小于100 这里是第#i 列:#list[i] < / li>
lite template
<c:forvar=item list=$list><c:if test=$for.index<100>
< li > 小于100 这里是第 $ ! for .index 列:$ ! item < / li>
</c:if>
<c:else>
< li > 不小于100 这里是第$ ! for .index 列:$ ! item < / li>
</c:else>
</c:for>
然后我们改变list数组里面的元素个数,对各个模板翻译执行的时间进行记录。结果如下(xp+ie6/ie8/firefox/chrome运行环境):
模板翻译时间对比表(第一次翻译并渲染数据 时间单位:毫秒)
List长度 | Yaya Template | EasyTemplate | jquery template | ace template | lite template | |
1 | ie6 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 16 15 12 4 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
10 | ie6 | 0 0 0 0 | 0 0 0 0 | 0 0 1 0 | 0 0 0 1 | 16 15 11 2 |
猜牌问题甲乙都知道桌子的抽屉里有16张扑克牌: 红桃AQ4 黑桃J84273 草色KQ546 方块A5 教授从这16张牌中挑出一张牌来,并把这张牌的点数告诉甲,把 |