from: http://lzyy.org/blog/archives/38

首先來說說,為什么要用javascript模板。以PHP為例,PHP本身就可以穿插于HTML之間,所以也算是一種模板語言,缺點就是代碼看起來會有點亂,尤其是融合了各種循環(huán),判斷,賦值等等操作(也不方便格式化),沒有做到結(jié)構(gòu)和數(shù)據(jù)分離。當(dāng)然PHP也有很多的模板引擎,使用這些模板引擎的一個缺陷就是,效率不如原生的PHP高。沒錯,可以生成緩存文件,但對于更新相對頻繁的站點就不行了。這個時候或許可以考慮javascript模板技術(shù)了。
使用了javascript模板,就把解析壓力交給了瀏覽器,服務(wù)端只需要提供要用到的數(shù)據(jù)即可。

這里要介紹的是JST(JAVASCRIPT TEMPLATE),它有什么特點呢?

  • 文件體積小壓縮后只有6K
  • 兼容主流瀏覽器包括IE6
  • 使用方便待會看下面的demo就知道了
  • 功能齊全,使用靈活如果用過php的模板,那么對JST的用法應(yīng)該就會比較熟悉了

使用方法

無論是數(shù)據(jù)還是模板,JST都是把這些放在textarea里的,當(dāng)然你可以設(shè)置為隱藏,這樣textarea就相當(dāng)于一個容器了,為什么是textarea?因為textarea的innerHTML能夠非常好地保持?jǐn)?shù)據(jù)結(jié)構(gòu),而且不會被瀏覽器解析。所以是理想的藏身之所。
要使用JST,第一步當(dāng)然是載入對應(yīng)的js文件

<html>
<head>
<script language="javascript" src="trimpath/template.js"></script>
...
</head>
...
</html>

然后創(chuàng)建數(shù)據(jù),一些objet和array

<script language="javascript">
var data = {
products : [ { name: "mac", desc: "computer",
price: 1000, quantity: 100, alert:null },
{ name: "ipod", desc: "music player",
price:  200, quantity: 200, alert:"on sale now!" },
{ name: "cinema display", desc: "screen",
price:  800, quantity: 300, alert:"best deal!" } ],
customer : { first: "John", last: "Public", level: "gold" }
};
</script>

接下來就是待解析的模板了,放在了一個id為cart_jst的textarea里

<textarea id="cart_jst" style="display:none;">
Hello ${customer.first} ${customer.last}.<br/>
Your shopping cart has ${products.length} item(s):
<table>
<tr><td>Name</td><td>Description</td>
<td>Price</td><td>Quantity &amp;amp; Alert</td></tr>
{for p in products}
<tr><td>${p.name|capitalize}</td><td>${p.desc}</td>
<td>$${p.price}</td><td>${p.quantity} : ${p.alert|default:""|capitalize}</td>
</tr>
{forelse}
<tr><td colspan="4">No products in your cart.</tr>
{/for}
</table>
{if customer.level == "gold"}
We love you!  Please check out our Gold Customer specials!
{else}
Become a Gold Customer by buying more stuff here.
{/if}
</textarea>

下面這個就是關(guān)鍵的解析語句了,還是很簡單的

<script language="javascript">
//一句話搞定解析并賦值,cart_jst是textarea的id,data是之前定義的數(shù)據(jù)
//現(xiàn)在result已經(jīng)包含解析過的模板文件內(nèi)容了
var result = TrimPath.processDOMTemplate("cart_jst", data);
 
//也可以分兩步走,先解析,再賦值
var myTemplateObj = TrimPath.parseDOMTemplate("cart_jst");
var result  = myTemplateObj.process(data);
//也可以給這個模板一個新的數(shù)據(jù)源
var result2 = myTemplateObj.process(differentData);
 
//輸出結(jié)果
someOutputDiv.innerHTML = result;
</script>

最后的內(nèi)容就像這樣

Hello John Public.<br/>
Your shopping cart has 3 item(s):
<table>
<tr><td>Name</td><td>Description</td>
<td>Price</td><td>Quantity &amp;amp; Alert</td></tr>
<tr><td>MAC</td><td>computer</td>
<td>$1000</td><td>100 : </td>
</tr>
<tr><td>IPOD</td><td>music player</td>
<td>$200</td><td>200 : ON SALE NOW!</td>
</tr>
<tr><td>CINEMA DISPLAY</td><td>screen</td>
<td>$800</td><td>300 : BEST DEAL!</td>
</tr>
</table>
We love you!  Please check out our Gold Customer specials!

也可以不把模板放到textarea里,直接解析String也是可以的

<script language="javascript">
var myStr = "Hello ${customer.first} ${customer.last}, Welcome back!";
result = myStr.process(data);
 
//或者直接使用process方法,還省去了一個中間變量
result = "Hello ${customer.first} ${customer.last}, Welcome back!".process(data);
//The result: "Hello John Public, Welcome back!"
//跟下面的效果是一樣
result = "Hello " + customer.first + " " + customer.last + ", Welcome back!";
 
//或者先解析,再賦值
var myTemplateObj = TrimPath.parseTemplate(myStr);
var result  = myTemplateObj.process(data);
var result2 = myTemplateObj.process(differentData);
</script>

提示:也可以把jst模板文件放到服務(wù)端,等要用時再去load,如$.getScript()

模板語言

真是麻雀雖小,五臟俱全啊,看看下面的例子就知道了

跟Smarty一樣,JST也可以通過在變量后面加|在模板里”包裝”變量

${customer.firstName}
${customer.firstName|capitalize}
${customer.firstName|default:"no name"|capitalize}

if else判斷語句

{if customer != null &amp;amp;&amp;amp; 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 &amp;amp;&amp;amp; returnURL != 'main'}?goto=${returnURL}{/if}">Login</a>

循環(huán)輸出

{for x in customer.getRecentOrders()}
//這里的x_index指代循環(huán)的次數(shù),使用方法為"變量名_index"
${x_index} : ${x.orderNumber} <br/>
//如果customer.getRecentOrders()長度為0或為null
{forelse}
You have no recent orders.
{/for}

自定義變量

{var temp = crypto.generateRandomPrime(4096)}
Your prime is ${temp}

cdata,不接受解析,保持原來的數(shù)據(jù),就跟xml里的CDATA一樣,有兩種使用方法,效果都一樣

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

在模板內(nèi)執(zhí)行javascript

{eval}
//str是從js處傳過來的參數(shù)
//如TrimPath.parseDOMTemplate('ev').process({str:'hello JST'});
alert(str);
{/eval
 
{eval EOF}
跟上面的一樣
EOF

以上演示代碼直接從官方網(wǎng)站拿來的,為了照顧像我一樣看見E文就頭大的同學(xué)

注意
如果在textarea的模板里又套了一個textarea會出錯,可以通過自定義變量解決,或者避免這樣的情況發(fā)生。

<textarea id="myTemplate" style="display:none">
{var textarea = "textarea"}
<form>
<${textarea} name="myField">
Some stuff here
</${textarea}>
</form>
</textarea>