本文翻译自JavaScript Template Syntax
表达式与表达式修饰符
${expr}
${expr|modifier}
${expr|modifier1|modifier2|...|modifierN}
${expr|modifier1:argExpr1_1}
${expr|modifier1:argExpr1_1,argExpr1_2,...,argExpr1_N}
${expr|modifier1:argExpr1_1,argExpr1_2|...|modifierN:argExprN_1,argExprN_2,...,argExprN_M}
expr
可以是不包含右花括号}
的任何合法JavaScript表达式修饰符的格式是
modifierName[:argExpr1[,argExpr2[,argExprN]]]
argExpr
可以是任何合法的expr
Examples: ${customer.firstName} ${customer.firstName|capitalize} ${customer.firstName|default:"no name"|capitalize} ${article.getCreationDate()|default:new Date()|toCalenderControl:"YYYY.MM.DD",true,"Creation Date"} ${(lastQuarter.calcRevenue() - fixedCosts) / 1000000}
这里有一份内置的修饰符列表,你也可以通过TrimPath提供的API来创建自定义的修饰符。
表达式还可以写成${% customer.firstName %}
这种形式,多出的%
字符允许你的表达式中出现花括号}
。例如:
Visit our ${% emitLink('Solutions and Products',
{ color: 'red', blink: false }) %}
表达式中的空白字符是可选的,你也可以写成下面的格式:
${%customer.firstName%}
${%customer.firstName|capitalize%}
声明
声明标签可以嵌套使用。
控制流
{if testExpr}
{elseif testExpr}
{else}
{/if}
testExpr
可以是任何不包含}
的JavaScript表达式testExpr
不需要被(
和)
包围
示例:
{if customer != null && customer.balance > 1000}
We love you!
{/if}
{if user.karma > 100}
Welcome to the Black Sun.
{elseif user.isHero}
Sir, yes sir! Welcome!
{if user.lastName == "Yen"}
Fancy some apple pie, sir?
{/if}
{/if}
<a href="/login{if returnURL != null && returnURL != 'main'}?goto=${returnURL}{/if}">Login</a>
TrimPath引擎还定义了一个帮助方法叫做defined(str)
,它可以检查给定的参数是否是JavaScript中的undefined
值。通过它可以很方便的判断某个值是否被定义:
{if defined('adminMessage')}
System Administrator Important NOTICE: ${adminMessage}
{/if}
循环
{for varName in listExpr}
{/for}
{for varName in listExpr}
...循环主体...
{forelse}
...当listExpr的值是null或者长度为0时执行此区域...
{/for}
varName
可以是任何合法的JavaScript变量名称listExpr
是一个JavaScirpt表达式,它执行结果必须是数组,对象或是null值中的1种。listExpr
只会被执行一次。
循环过程中可以访问2个额外的变量:
- __LIST__varName
- 保存了listExpr
的执行结果
- varName_index
- 保存了循环过程中当前值对应的索引或是键名。
示例:
{for x in customer.getRecentOrders()}
${x_index} : ${x.orderNumber} <br/>
{forelse}
You have no recent orders.
{/for}
以下是与上边代码功能相同的伪代码
var __LIST__x = customer.getRecentOrders();
if (__LIST__x != null && __LIST__x.length > 0) {
for (var x_index in __LIST__x) {
var x = __LIST__x[x_index];
${x_index} : {$x.orderNumber} <br/>
}
} else {
You have no recent orders.
}
变量声明
{var varName}
{var varName = varInitExpr}
varName
可以是任何合法的JavaScript变量名varinitExpr
不可以包含}
示例:
{var temp = crypto.generateRandomPrime(4096)}
Your prime is ${temp}.
宏声明
{macro macroName(arg1, arg2, ...argN)}
...body of the macro...
{/macro}
- 一个宏就像是一个JavaScript函数,只是宏的主体是另一个模板而不是JavaScript代码。
- 也就是说宏的主体可以包含TrimPath表达式和声明。
macroName
可以是任何合法的JavaScript变量名。- 宏执行后的返回值是一个字符串。
- 可以通过
${macroName()}
的形式调用一个宏。
示例:
{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])}
${htmlList([ "Purple State", "Blue State", "Red State" ], "ol")}
{var saved = htmlList([ 100, 200, 300 ])}
${saved} and ${saved}
默认情况下,宏只能在定义它的模板中使用。如果你想导出一个宏以便在其他模板中复用,一种方法就是把保存一份宏的引用到contentObject
中(contentObject
就是你调用template.process
方法时传递的参数)。在调用process
方法前先设置'contextObject['exported'] = {};
,然后可以在末班中通过这种方法获得宏的引用:
{macro userName(user)}
{if user.aliasName != null && user.aliasName.length > 0}
${user.aliasName}
{else}
${user.login}
{/if}
{/macro}
${exported.userName = userName |eat}
你也可以直接设置contextObject['exported'] = contextObject;
,这样做也可以工作,但是会造成循环引用。
CDATA文本块
{cdata}
...此区域内的文本不会被引擎解析...
{/cdata}
{cdata EOF}
...此区域内的文本不会被引擎解析...
EOF
你可以使用{cdata EOF}...EOF
或是{cdata}...{/cdata}
这2中语法来告诉模板引擎忽略对特定文本块的处理。这些文本块会被直接输出,其中包含的任何标签都不会被解析。当你需要通过JavaScript模板生成其他JavaScript模板时会非常方便。
- EOF
可以是任何不包含}
的标记字符串。标记字符串用来标示一个文本块的结束。
- 文本块可以包含换行符,输出时模板引擎会保留这些换行。
示例:
Hello, ${user.firstName}.
An example of expression markup in JST looks like...
{cdata END_OF_THE_CDATA_SECTION}
${customer.firstName} ${customer.lastName}
END_OF_THE_CDATA_SECTION
...which shows a customer's name.
Let me repeat that...
{cdata}
${customer.firstName} ${customer.lastName}
{/cdata}
...will show a customer's name.
以上模板会输出以下内容:
Hello, Steve.
An example of expression markup in JST looks like...
${customer.firstName} ${customer.lastName}
...which shows a customer's name.
Let me repeat that...
${customer.firstName} ${customer.lastName}
...will show a customer's name.
嵌入的JavaScript
eval代码块
{eval}
...模板引擎解析模板时将执行此区域代码...
{/eval
{eval EOF}
...模板引擎解析模板时将执行此区域代码...
EOF
EOF
可以是任何不包含}
的文本。
{eval}
块可以用来在模板中定义多行的JavaScript事件处理函数。例如:
{eval}
sel_onchange = function() {
...事件处理函数定义...;
}
{/eval}
需要注意的是,在上边的事例中我们_没有_使用var
关键字来声明变量,例如var sel_onchange = function() {...}
。这是为了保证sel_onchange
在全局作用域中以便可以被事件处理机制访问到。
minify块
{minify}
...此处可以写多行代码,模板引擎输出时会合并成一行...
{/minify
{minify EOF}
...此处可以写多行代码,模板引擎输出时会合并成一行...
EOF
{minify}
块允许你在HTML属性中嵌入多行的JavaScript或CSS代码。对JavaScript来说,这可以很方便的编写多行的事件处理函数。例如:
<select onchange="{minify}
...复杂的多行事件处理逻辑...;
this.enabled = false;
{/minify}">
<select onchange="{minify END_OF_JS}
...复杂的多行事件处理逻辑...;
this.enabled = false;
END_OF_JS">
对应CSS来说,{minify}
允许你方便的嵌入多行行内样式代码,例如:
<div id="commentPanel"
style="{minify}
display:none;
margin: 1em;
border: 1px solid #333;
background: #eee;
padding: 1em;
{/minify}">
</div>