from: http://lzyy.org/blog/archives/38
首先來說說,為什么要用javascript模板。以PHP為例,PHP本身就可以穿插于HTML之間,所以也算是一種模板語言,缺點就是代碼看起來會有點亂,尤其是融合了各種循環,判斷,賦值等等操作(也不方便格式化),沒有做到結構和數據分離。當然PHP也有很多的模板引擎,使用這些模板引擎的一個缺陷就是,效率不如原生的PHP高。沒錯,可以生成緩存文件,但對于更新相對頻繁的站點就不行了。這個時候或許可以考慮javascript模板技術了。
使用了javascript模板,就把解析壓力交給了瀏覽器,服務端只需要提供要用到的數據即可。
這里要介紹的是JST(JAVASCRIPT TEMPLATE),它有什么特點呢?
- 文件體積小壓縮后只有6K
- 兼容主流瀏覽器包括IE6
- 使用方便待會看下面的demo就知道了
- 功能齊全,使用靈活如果用過php的模板,那么對JST的用法應該就會比較熟悉了
使用方法
無論是數據還是模板,JST都是把這些放在textarea里的,當然你可以設置為隱藏,這樣textarea就相當于一個容器了,為什么是textarea?因為textarea的innerHTML能夠非常好地保持數據結構,而且不會被瀏覽器解析。所以是理想的藏身之所。
要使用JST,第一步當然是載入對應的js文件
<html> <head> <script language="javascript" src="trimpath/template.js"></script> ... </head> ... </html>
然后創建數據,一些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; 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>
下面這個就是關鍵的解析語句了,還是很簡單的
<script language="javascript"> //一句話搞定解析并賦值,cart_jst是textarea的id,data是之前定義的數據 //現在result已經包含解析過的模板文件內容了 var result = TrimPath.processDOMTemplate("cart_jst", data); //也可以分兩步走,先解析,再賦值 var myTemplateObj = TrimPath.parseDOMTemplate("cart_jst"); var result = myTemplateObj.process(data); //也可以給這個模板一個新的數據源 var result2 = myTemplateObj.process(differentData); //輸出結果 someOutputDiv.innerHTML = result; </script>
最后的內容就像這樣
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; 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模板文件放到服務端,等要用時再去load,如$.getScript()
模板語言
真是麻雀雖小,五臟俱全啊,看看下面的例子就知道了
跟Smarty一樣,JST也可以通過在變量后面加|在模板里”包裝”變量
${customer.firstName} ${customer.firstName|capitalize} ${customer.firstName|default:"no name"|capitalize}
if else判斷語句
{if customer != null &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; returnURL != 'main'}?goto=${returnURL}{/if}">Login</a>
循環輸出
{for x in customer.getRecentOrders()} //這里的x_index指代循環的次數,使用方法為"變量名_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,不接受解析,保持原來的數據,就跟xml里的CDATA一樣,有兩種使用方法,效果都一樣
{cdata} ...text emitted without JST processing... {/cdata} {cdata EOF} ...text emitted without JST processing... EOF
在模板內執行javascript
{eval} //str是從js處傳過來的參數 //如TrimPath.parseDOMTemplate('ev').process({str:'hello JST'}); alert(str); {/eval {eval EOF} 跟上面的一樣 EOF
以上演示代碼直接從官方網站拿來的,為了照顧像我一樣看見E文就頭大的同學
注意
如果在textarea的模板里又套了一個textarea會出錯,可以通過自定義變量解決,或者避免這樣的情況發生。
<textarea id="myTemplate" style="display:none"> {var textarea = "textarea"} <form> <${textarea} name="myField"> Some stuff here </${textarea}> </form> </textarea>
jCT
專題
http://achun.javaeye.com/category/33268
在線demo
http://jsct.googlecode.com/svn/trunk/jCT/example/index.html