码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript Template JST模板引擎----Trimpath [转]

时间:2014-05-26 15:53:10      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:des   style   c   class   code   java   

官方网址:http://trimpath.com/project/wiki/JavaScriptTemplates

Trimpath JavaScript 是个轻量级的,基于JavaScript的,跨浏览器,采用APL/GPL开放源代码协议的,可以让你轻松进行基于模板编程方式的纯JS引擎。

它有如下的特点:
1、采用标准的JavaScript编写,支持跨浏览器
2、模板语法类似于:FreeMarker,Velocity,Smarty
3、采用简易的语言来描述大段的字串以及Dom/DHTML操作
4、可以很方便的解析XML文件格式的数据到指定模板。

采 用该引擎,可以让它来完全处理View方面的事情,服务端Module直接输出Data就可以。让你的MVC模式连成一体,而且由于View由浏览器来处 理,大大减少了服务器的负担,用来构建Ajax技术的网络信息系统应用是一个非常好的选择。下面将通过翻译该站的文章来给大家介绍这个JST引擎的使用。

网站地址:

  http://code.google.com/p/trimpath/wiki/JavaScriptTemplates

如果大家等不及看我翻译或者不满意翻译质量,请看上面网站的英文原文。

快速演示:

  1.   <html>
  2.     <head>
  3.       <script language="javascript" src="trimpath/template.js"></script>
  4.     </head>
  5. <body>
  6.   <div id="outputDiv">
  7.   </div>
  8.   <script language="javascript">
  9.     var data = {
  10.         products : [ { name: "mac", desc: "computer",     
  11.                        price: 1000, quantity: 100, alert:null },
  12.                      { name: "ipod", desc: "music player",
  13.                        price:  200, quantity: 200, alert:"on sale now!" },
  14.                      { name: "cinema display", desc: "screen",      
  15.                        price:  800, quantity: 300, alert:"best deal!" } ],
  16.         customer : { first: "John", last: "Public", level: "gold" }
  17.     };
  18.   </script>
  19. <textarea id="cart_jst" style="display:none;">
  20.     Hello ${customer.first} ${customer.last}.<br/>
  21.     Your shopping cart has ${products.length} item(s):
  22.     <table>
  23.      <tr><td>Name</td><td>Description</td>
  24.          <td>Price</td><td>Quantity & Alert</td></tr>
  25.      {for p in products}
  26.          <tr><td>${p.name|capitalize}</td><td>${p.desc}</td>
  27.              <td>$${p.price}</td><td>${p.quantity} : ${p.alert|default:""|capitalize}</td>
  28.              </tr>
  29.      {forelse}
  30.          <tr><td colspan="4">No products in your cart.</tr>
  31.      {/for}
  32.     </table>
  33.     {if customer.level == "gold"}
  34.       We love you!  Please check out our Gold Customer specials!
  35.     {else}
  36.       Become a Gold Customer by buying more stuff here.
  37.     {/if}
  38.   </textarea>
  39.   <script language="javascript">
  40.     // The one line processing call...
  41.     var result = TrimPath.processDOMTemplate("cart_jst", data);
  42.     // Voila!  That‘s it -- the result variable now holds
  43.     // the output of our first rendered JST.

  44.     // Alternatively, you may also explicitly parse the template...
  45.     var myTemplateObj = TrimPath.parseDOMTemplate("cart_jst");

  46.     // Now, calls to myTemplateObj.process() won‘t have parsing costs...
  47.     var result  = myTemplateObj.process(data);

  48.     // Setting an innerHTML with the result is a common last step...
  49.     document.getElementById("outputDiv").innerHTML = result;
  50.     // You might also do a document.write() or something similar...
  51.   </script>
  52. </body>
  53. </html>
复制代码


实际效果:
bubuko.com,布布扣




JST十分钟简介

JST API
JST Markup Syntax
JST Standard Modifiers
JST Downloads
JST Community Wiki
JST Browser Compatibility
JST Online Demo

1、API
首先到下载页面下载 template.js
然后在你的JSP/ASP/PHP等文件中引用

  1. <script language="javascript" src="trimpath/template.js"></script>
复制代码



当你引用了template.js文件之后,脚本将创建一个名叫“trimpath"的物件给你使用。

TrimPath Object
这个物件是一个全局的单一变量,也是所有trimpath组件的访问入口,除了它自身,我们尝试建立一个清晰的命名空间给您使用。

下面是 Trimpath 定义的方法:

  1. TrimPath.parseDOMTemplate ( elementId, optionalDocument )
复制代码



得到页面中ID为elementId的Dom组件的InnerHTML,并将其解析成一个模板,这个方法返回一个templateObject对象(下面将详细描述),解析出错时将抛出一个异常,下面是这个方法的参数:
  elementId               DOM组件,其innerhtml将用来做模板
  optionalDocument     一个可选参数,在使用iframe,frameset或者默认多文档时会有用
通常用来做模板的DOM元素是一个隐藏的<textarea>,如下面的例子

  1. <textarea id="elementId" style="display:none;"> template body </textarea>
复制代码




TrimPath.processDOMTemplate ( elementId, contextObject, optionalFlags, optionalDocument )
一 个辅助函数,里面调用了TrimPath.parseDOMTemplate() 和 then the process() 方法以获得templateObject。输出的是templateObject.process() 中返回的对象。解析出错时将抛出一个错误。下面是这个方法的参数:

elementId         包含模板内容的DOM元素ID
contextObject     参考templateObject.process()
optionalFlags       参考templateObject.process()
optionalDocument 参考TrimPath.parseDOMTemplate

TrimPath.parseTemplate ( templateContentStr, optionalTemplateName )
解析模板方法,将一个字符串做为模板解析并返回一个templateObject
参数表:

templateContentStr   符合JST语法的字符串,例如: "Hello ${firstName} ${lastName}"
optionalTemplateName 一个可选的字符串用来指定模板名称,辅助查错。

The templateObject
TrimPath.parseTemplate() 和 TrimPath.parseDOMTemplate()的成功运行将产生一个 templateObject 它只有一个主方法

templateObject.process ( contextObject, optionalFlags )

这个方法将模板和数据结合在一起,可以重复调用,如果没有重新解析,templateObjects的缓存和重用将获得最好的系统性能。这个函数的返回值是一个经过“渲染”过的模板的字符串。


参数contextObject 必须是一个对象,并将成为模板的一个访问域,比如一个模板是:${a},那么contextObject.a必须是可以访问到的。同样${a.b.c}, contextObject.a.b.c也是可以访问到的。
注 意:contextObject 可以是javascript中的任意对象,包含字符串, 数字, 日期, 对象和函数。所以${groupCalender(new Date())} 可以这样来调用contextObject.groupCalender(new Date())。当然,你必须自己编程实现groupCalender() 这个函数。

参数optionalFlags 可以是空值,也可以是一个下面列表描述的对象:
throwExceptions 默认是false,当true的时候,process() 方法将重新抛出异常,当false的时候,任何异常将停止解析模板,并在方法返回值包含一个出错信息。
keepWhitespace 默认是falsel,当值为true时,模板的空白将保留。当为false时,空白(换行、空格、TAB)将被截取。

String.prototype.process() 方法

String.prototype.process ( contextObject, optionalFlags )
做为一个便捷的方式为string对象加入一个process()的方法,让它来执行解析模板的动作。参数跟process()一样。

  1.   var result = "hello ${firstName}".process(data)
  2.   // ...is equivalent to...
  3.   var result = TrimPath.parseTemplate("hello ${firstName}").process(data);
复制代码




添加自定义标识符

如果要采用自定义标识符,你必须把他们放在_MODIFERS 这个对象中,这些标识符集将被添加到contextObject 对象中,然后最终传给process()解析。每一个自定义标识符必须是一个函数并且至少有一个字符串参数输入和一个字符串输出。
例子:

  1.   var myModifiers = {
  2.   hello : function(str, greeting) {
  3.     if (greeting == null)
  4.       greeting = "Hello";
  5.     return greeting + ", " + str;
  6.   },
  7.   zeroSuffix : function(str, totalLength) {
  8.     return (str + "000000000000000").substring(0, totalLength);
  9.   }
  10. };
  11. var myData = {
  12.   firstName : "John",
  13.   getCurrentPoints : function() { /* Do something here... */ return 12; }
  14. }

  15. myData._MODIFIERS = myModifiers;

  16. "${firstName}".process(myData) == "John"
  17. "${firstName|hello}".process(myData) == "Hello, John"
  18. "${firstName|hello:"Buenos Dias"}".process(myData) == "Buenos Dias, John"
  19. "${firstName|hello:"Buenos Dias"|capitalize}".process(myData) == "BUENOS DIAS, JOHN"

  20. "${getCurrentPoints()}".process(myData) == "12"
  21. "${getCurrentPoints()|zeroSuffix:4}".process(myData) == "1200"
复制代码






JST 的语法和语句

语法

  1. ${expr}
  2. ${expr|modifier}
  3. ${expr|modifier1|modifier2|...|modifierN}
  4. ${expr|modifier1:argExpr1_1}
  5. ${expr|modifier1:argExpr1_1,argExpr1_2,...,argExpr1_N}
  6. ${expr|modifier1:argExpr1_1,argExpr1_2|...|modifierN:argExprN_1,argExprN_2,...,argExprN_M}
复制代码


表达式可以是除了“}”之外的任何合法的javascript字符串
标识符看起来像这种结构:modifierName[:argExpr1[,argExpr2[,argExprN]]]

一个带参数的表达式例子

  1. ${customer.firstName}
  2. ${customer.firstName|capitalize}
  3. ${customer.firstName|default:"no name"|capitalize}
  4. ${article.getCreationDate()|default:new Date()|toCalenderControl:"YYYY.MM.DD",true,"Creation Date"}
  5. ${(lastQuarter.calcRevenue() - fixedCosts) / 1000000}
复制代码


一个表达式也可以像下面一样通过添加“%”字符来标识,这个可以避免在你的表达式中出现“}”时出错的情况。

比如:

  1. Visit our ${% emitLink(‘Solutions and Products‘,
  2.                 { color: ‘red‘, blink: false }) %} page.

  3. The extra spaces are actually not necessary, like...
  4. ${%customer.firstName%}
  5. ${%customer.firstName|capitalize%}
复制代码


语句
JST语句就像是javascript语句一样,也有if/else/for/function这些句子

分支控制语句

  1. {if testExpr}
  2.   {elseif testExpr}
  3.   {else}
  4. {/if}
复制代码


上述testExpr 是一个合法的javascript判定式

例子

  1. {if customer != null && customer.balance > 1000}
  2.   We love you!
  3. {/if}

  4. {if user.karma > 100}
  5.     Welcome to the Black Sun.
  6. {elseif user.isHero}
  7.     Sir, yes sir! Welcome!
  8.     {if user.lastName == "Yen"}
  9.       Fancy some apple pie, sir?
  10.     {/if}
  11. {/if}

  12. <a href="/login{if returnURL != null && returnURL != ‘main‘}?goto=${returnURL}{/if}">Login</a>
复制代码


*JST引擎还包含一个辅助函数defined(str),这个可以测试一个变量是否已经被定义。

比如这段代码判断管理员发送了消息给你

  1. {if defined(‘adminMessage‘)}
  2.   System Administrator Important NOTICE: ${adminMessage}
  3. {/if}
复制代码



循环语句

  1. {for varName in listExpr}
  2. {/for}

  3. {for varName in listExpr}
  4.   ...main body of the loop...
  5. {forelse}
  6.   ...body when listExpr is null or listExpr.length is 0...

  7. {/for}
复制代码


*varName 必须是一个javascript的合法变量名
*listExpr 可以是一个数组,对象或者为空,而且只能被赋值一次
例子

  1. Two variables are bound in the main body of the loop:
  2.   __LIST__varName - holds the result of evaluating listExpr.
  3.   varName_index   - this is the key or counter used during iteration.

  4. Examples:
  5. {for x in customer.getRecentOrders()}
  6.   ${x_index} : ${x.orderNumber} <br/>
  7. {forelse}
  8.   You have no recent orders.
  9. {/for}

  10. Converted pseudo-code for the above...
  11. var __LIST__x = customer.getRecentOrders();
  12. if (__LIST__x != null && __LIST__x.length > 0) {
  13.   for (var x_index in __LIST__x) {
  14.     var x = __LIST__x[x_index];
  15.     ${x_index} : {$x.orderNumber} <br/>
  16.   }
  17. } else {
  18.   You have no recent orders.
  19. }
复制代码



定义变量

{var varName}
{var varName = varInitExpr}
*varName必须是一个合法的javascript变量名
*varInitExpr必须是一个没有包含"}"的字符串

例子:

  1. {var temp = crypto.generateRandomPrime(4096)}
  2. Your prime is ${temp}.
复制代码


宏定义
   {macro macroName(arg1, arg2, ...argN)}
   ...body of the macro...
{/macro}

*宏类似于一个javascript函数,不同点在于宏的主体是另外一个包含了诸如控制语句、循环语句的JST模板

*宏的名称必须是一个合法javascript变量名
*宏的返回值是一个字符创
*使用宏可以采用这种语法 :${macroName()}
一个使用宏的例子

  1. {macro htmlList(list, optionalListType)}
  2.   {var listType = optionalListType != null ? optionalListType : "ul"}
  3.   <${listType}>
  4.     {for item in list}  
  5.     <li>${item}</li>
  6.     {/for}
  7.   </${listType}>
  8. {/macro}

  9. Using the macro...
  10. ${htmlList([ 1, 2, 3])}
  11. ${htmlList([ "Purple State", "Blue State", "Red State" ], "ol")}
  12. {var saved = htmlList([ 100, 200, 300 ])}
  13. ${saved} and ${saved}
复制代码


运行上述语句将出现

*1
*2
*3


这样的列表。只需将数据列表赋值给htmlList这个宏,就会帮你把数据通过<li>方式列出来,聪明的你很快就会把它改成<option><td>等应用了。

从宏的访问域来说,默认情况下它是每个模板私有的,但是如果你想定义
一个宏库的话,那么也许你需要在process()之前先定义可以导出宏:contextObject[‘exported‘] ={};
下面是例子:

  1.   {macro userName(user)}
  2.   {if user.aliasName != null && user.aliasName.length > 0}
  3.     ${user.aliasName}
  4.   {else}
  5.     ${user.login}
  6.   {/if}
  7. {/macro}
  8. ${exported.userName = userName |eat}
复制代码


另外,你也可以设置 contextObject[‘exported‘] = contextObject;它也可以正常的工作。

CDATA 文本区段
[code]
{cdata}
   ...text emitted without JST processing...
{/cdata}

{cdata EOF}
   ...text emitted without JST processing...
EOF

 

使用模板引擎,让开发模式更清晰,也让职责更明确,对维护对开发都是一件双赢的事情。

曾经接触过SmartTemplate和Velocity,如果纯从编写前端模板来说,都不是太难的事情,大部分流行的模板引擎都支持类似的语法, 如Smarty以及本文要介绍的JS模板引擎Trimpath。

如果一个项目,需要前端大量的重绘数据来展现,大量的DOM树会随用户的操作而产生变化,这时,无论从功能上,还是性能上,以及维护的方便性 上,Trimpath template都是一个不错的选择。唯一遗憾的是,已经有近2年的时间没有更新了,是没有bug还是作者已经放弃掉了都不得而知。因为是好的东西,就不 管那么多了。

Trimpath支持的语法:

1)变量声明

{var yihui = ‘一回‘}
${yihui} // 一回


2)变量(表达式)调节器

Trimpath的变量调节器是可以扩展的,在使用上和Smarty几乎看不出区别:
{var yihui = ‘<hr />‘}
${yihui|escape|capitalize} // &LT;HR /&GT;

Trimpath默认支持以下调节器:capitalize,escape(h),default,eat。同时支持表达式的调节,如:
${new Date()|toFormat:‘YYYY-MM-DD‘}
你也可以根据自己的需要进行扩展,上面的toFormat就是自定义的。


3)条件控制

{var yihui = ‘b‘}
{if yihui == ‘a‘}
      ${yihui}等于a
{else}
      ${yihui}不等于a
{/if}


4)循环控制

假设数据为:
var datas = [
   {‘type‘ : ‘market‘, ‘name‘ : ‘市场基金‘, ‘value‘ : 102.44},
{‘type‘ : ‘channel‘, ‘name‘ : ‘渠道基金‘, ‘value‘ : 54},
{‘type‘ : ‘customer‘, ‘name‘ : ‘客服考核‘, ‘value‘ : 98}
];

模板可以这样写:
<table width="400" cellspacing="0" cellpadding="0" border="1">
{for x in datas}
    < tr>
     < td>${x.type}</td>
      < td>${x.name}</td>
      < td>${x.value}</td>
   < /tr>
{forelse}
  < tr>
      < td>没有数据</td>
   < /tr>
{/for}
< /table>
这样书写,是不是要比字符串拼接更直观,维护也方便呢?


5)支持宏定义

宏可以理解为能够完成一定功能的函数,将通用的功能组织起来,有利于代码复用:
{macro htmlList(list, optionalListType)}
    {var listType = optionalListType != null ? optionalListType : "ul"}
   < ${listType}>
      {for item in list}
       < li>${item}</li>
      {/for}
    < /${listType}>
{/macro}

${htmlList([1,2,3], ‘ol‘)}


6)CDATA区域

CDATA区域的内容将不被Trimpath解析,会原样输出
{cdata}hello,${yihui}{/cdata}


7)内联JS代码

eval区域内可以直接书写JS代码:
<select onchange="sel_onchange()">
   < option value="1">1</option>
   < option value="2">2</option>
< /select>
{eval}
   sel_onchange = function() {
      alert(‘我不小心被change了‘);
   }
{/eval}

JavaScript Template JST模板引擎----Trimpath [转],布布扣,bubuko.com

JavaScript Template JST模板引擎----Trimpath [转]

标签:des   style   c   class   code   java   

原文地址:http://www.cnblogs.com/yanger/p/3746199.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!