google closure 筆記-SOY template

一 使用js模板

closure template 目前支持Javajs。可是模板語法的設計不依賴於任何現成的語言,因此理論上能夠支持任何語言,只是暫時只有java編譯器。javascript

使用js模板:編寫模板文件 .soy文件,而後用一個java編寫的編譯器將其編譯爲js文件,這個編譯好的js文件會提供一個函數來輸出模板內容,html

只須要引入這個js文件而後在js中調用這個函數就能夠獲得模板的內容(內容是一個字符串)。java

1, 下載工具包git

 http://closure-templates.googlecode.com/files/closure-templates-for-javascript-latest.zipapi

解壓以後會獲得兩個文件:app

SoyToJsSrcCompiler.jar, java編寫的編譯器,能夠把soy模板編譯爲js文件dom

soyutils.js,編譯器編譯模板時須要使用的工具類。函數

2 模板語法工具

一個完整的模板hello.soy 源碼以下ui

 

[javascript]  view plain  copy
 
  1. 1 {namespace demo.hello}  
  2. /** 
  3. 3   * Says hello to the world. 
  4. 4   */  
  5. 5 {template .helloWorld}  
  6. 6 Hello world!  
  7. 7 {/template}  



 

第一行是聲明命名空間

第二行是註釋,注意,這個註釋必須得加,否則編譯器會報錯

第5行是模板名,是相對於demo.hello命名空間的,即爲demo.hello.helloWorld

第6行是輸出的內容

第7行是閉合標籤

 

3 編譯模板

SoyToJsSrcCompiler.jar能夠將soy文件編譯爲js文件,編譯器的使用以下

java -jar ../SoyToJsSrcCompiler.jar --outputPathFormat hello.js hello.soy

 

編譯好的js文件會生成一個全局變量: demo.hello.helloWorld 函數,這個函數返回一個字符串 就是編譯好的模板的內容。

使用此模板時只須要document.write(demo.hello.helloWorld())便可。

 

4 使用模板

新建一個hello.html,內容以下

 

[javascript]  view plain  copy
 
  1.  1 <html>  
  2.  2 <head>  
  3.  3     <title>The Hello World of Closure Templates</title>  
  4.  4     <script type="text/javascript" src="../soyutils.js"></script>  
  5.  5     <script type="text/javascript" src="hello.js"></script>  
  6.  6 </head>  
  7.  7 <body>  
  8.  8     <script type="text/javascript">  
  9.  9     // Exercise the .helloWorld template  
  10. 10     document.write(demo.hello.helloWorld());  
  11. 11     </script>  
  12. 12 </body>  
  13. 13 </html>  



 

 

其中:

第3,4行分別引入了工具類和編譯好的模板文件,注意必定要先引入soyutils.js文件

第10行使用了模板hello.js提供的一個函數 demo.hello.helloWorld

 

5 添加另外一個模板

在上述的hello.soy文件後追加以下代碼

 

[javascript]  view plain  copy
 
  1.  9 /** 
  2. 10  * Greets a person using "Hello" by default. 
  3. 11  * @param name The name of the person. 
  4. 12  * @param? greetingWord Optional greeting word to use instead of "Hello". 
  5. 13  */  
  6. 14 {template .helloName}  
  7. 15     {if not $greetingWord}  
  8. 16     Hello {$name}!  
  9. 17     {else}  
  10. 18     {$greetingWord} {$name}!  
  11. 19     {/if}  
  12. 20 {/template}  



 

這個新加的模板中使用了兩個變量name和greetingWord。

編譯此模板後生成的hello.js代碼以下

 

[javascript]  view plain  copy
 
  1.  1 // This file was automatically generated from hello.soy.  
  2.  2 // Please don't edit this file by hand.  
  3.  3  
  4.  4 if (typeof demo == 'undefined') { var demo = {}; }  
  5.  5 if (typeof demo.hello == 'undefined') { demo.hello = {}; }  
  6.  6  
  7.  7  
  8.  8 demo.hello.helloWorld = function(opt_data, opt_sb) {  
  9.  9   var output = opt_sb || new soy.StringBuilder();  
  10. 10   output.append('Hello world!');  
  11. 11   return opt_sb ? '' : output.toString();  
  12. 12 };  
  13. 13  
  14. 14  
  15. 15 demo.hello.helloName = function(opt_data, opt_sb) {  
  16. 16   var output = opt_sb || new soy.StringBuilder();  
  17. 17   output.append((! opt_data.greetingWord) ? 'Hello ' + soy.$$escapeHtml(opt_data.name) + '!' : soy.$$escapeHtml(opt_data.greetingWord) + ' ' + soy.$$escapeHtml(opt_data.name) + '!');  
  18. 18   return opt_sb ? '' : output.toString();  
  19. 19 };  



 

能夠看到其中生成了兩個函數helloWorld和helloName

傳遞參數的方式很簡單,只須要在調用的時候把參數以key-value的形式傳入便可

 

[javascript]  view plain  copy
 
  1. 1 <html>  
  2.  2 <head>  
  3.  3     <title>The Hello World of Closure Templates</title>  
  4.  4     <script type="text/javascript" src="../soyutils.js"></script>  
  5.  5     <script type="text/javascript" src="hello.js"></script>  
  6.  6 </head>  
  7.  7 <body>  
  8.  8     <script type="text/javascript">  
  9.  9     // Exercise the .helloWorld template  
  10. 10     document.write(demo.hello.helloWorld());  
  11. 11     document.write("<br />" + demo.hello.helloName({name:"bob"}));     //傳遞參數  
  12. 12     document.write("<br />" + demo.hello.helloName({greetingWord:"wellcome:" ,name:"Lily"}));     //傳遞兩個參數  
  13. 13     </script>  
  14. 14 </body>  
  15. 15 </html>  



 

 

二 使用java模板

編寫模板的規則都是同樣的,依然按上面描述的方法來編寫一個soy文件,不一樣之處是:

js模板須要用一個編譯器編譯爲js文件,而java模板則直接在servlet中建立一個對象,這個對象能夠將soy文件編譯爲字符串。

 

下載工具包:

http://closure-templates.googlecode.com/files/closure-templates-for-java-latest.zip

 

新建HelloWorld.java文件:

  

[java]  view plain  copy
 
  1. import com.google.template.soy.SoyFileSet;  
  2.   import com.google.template.soy.data.SoyListData;  
  3.   import com.google.template.soy.data.SoyMapData;  
  4.   import com.google.template.soy.tofu.SoyTofu;  
  5.   5  
  6.   import java.io.File;  
  7.   7  
  8.   public class HelloWorld {  
  9.   9  
  10.  10     public static void main (String[] args) {  
  11.  11  
  12.  12         // Bundle the Soy files for your project into a SoyFileSet.  
  13.  13         SoyFileSet sfs = new SoyFileSet.Builder().add(new File("demo/hello.soy")).build();  
  14.  14  
  15.  15         // Compile the template into a SoyTofu object.  
  16.  16         // SoyTofu's newRenderer method returns an object that can render any template in file set.  
  17.  17         SoyTofu tofu = sfs.compileToJavaObj();  
  18.  18  
  19.  19         // Call the template with no data.  
  20.  20         System.out.println(tofu.newRenderer("demo.hello.helloWorld").render());  
  21.  21         System.out.println(tofu.newRenderer("demo.hello.helloName")  
  22.  22                             .setData(new SoyMapData(  
  23.  23                                     "name", "Ana",  
  24.  24                                             "additionalNames")  
  25.  25                             ).render());  
  26.  26     }  
  27.  27 }  

 

 

而後編譯運行代碼:

javac -classpath soy-latest.jar HelloWorld.java

java -classpath soy-latest.jar HelloWorld

結果老是出錯,不知道爲何⋯⋯

 

三 模板語法

 

語句:

模板中語句分爲兩類,html語句和模板語句,全部的模板語句都包括在{}中。通常語法以下:

{command value}

若是省略command,則默認爲print

 

變量:

變量以$符號開頭: 

{$name}

引用類型的數據,其輸出方式相似於js,

$a.0.c == $a[0].c == $a[0]["c"]

由於模板會自動刪除多餘空格,因此能夠用{sp}或者{nil}來添加空格

在namespace聲明中能夠指定escape

{namespace ns autoescape="contextual"}

模板支持的變量類型以下

Type              

Literal

Null

null

Boolean              

false or true

Integer

Decimal (e.g. -827) or hexadecimal (must begin with 0x and must use capital A-F, e.g. 0x1A2B).

Float

Must be in decimal and must either:

  • Have digits both before and after the decimal point (both can be a single 0), e.g. 0.5, -100.0, or
  • Have a lower-case e that represents scientific notation, e.g. -3e-3, 6.02e23.

Note: Even though the primitive type is named Float, it has the precision of a number in JavaScript or a double in Java.

String

Delimited by single quotes only. Closure Templates support these escape sequences: \\, \', \", \n, \r, \t, \b, \f, and \u#### where the #### can be any 4 hex digits to denote a Unicode code point.

List

A comma-separated list of heterogeneous values, for example: [1, 'two', [3, 'four']]. [] is the empty list.

Map

['key': 'value', <keyExpr><valueExpr>] maps keys to values.

Square brackets ([…]) delimit both lists and maps because braces ({…}) delimit commands.
[:] is the empty map. 

運算符

  •   - (unary)   not
  •   *   /   %
  •   +   - (binary)
  •   <   ]]]]>   <=   >=
  •   ==   !=
  •   and
  •   or
  •   ?: (ternary)

函數:

模板提供的基本函數以下:

Function

Usage

isFirst($var)

Use this with the foreach command. For more information see the foreach section of the Commands chapter.

isLast($var)

Use this with the foreach command. See more information in the foreach section of the Commands chapter.

index($var)

Use this with the foreach command. See more information in the foreach section of the Commands chapter.

hasData()

Checks whether a template data object was passed to this template. This function is rarely needed — use it only if all parameters to a template are optional, and thus the template may be called without any data object at all (omitted or null in javascript or null in Java). In this situation, the correct way to check for the presence of a parameter is {if hasData() and $myParam}. Alternatively, if you choose to always pass an empty data map (i.e. never pass null) to your template even when none of the optional params are needed, then you never have to use the hasData() function.

length($list)

The length of a list.

keys($map)

The keys in a map as a list. There is no guarantee on order.

round(number)                    

Round to an integer.

round(number, numDigitsAfterDecimalPoint)                                                

If numDigitsAfterDecimalPoint is positive, round to that number of decimal places; if numDigitsAfterDecimalPoint is negative, round to an integer with that many 0s at the end.

floor(number)

The floor of the number.

ceiling(number)

The ceiling of the number.

min(number, number)

The min of the two numbers.

max(number, number)

The max of the two numbers.

randomInt(rangeArg)

A random integer in the range [0, rangeArg - 1] (where rangeArg must be a positive integer). 

註釋:

  • // begins a rest-of-line comment
  • /* comment */ delimit an arbitrary comment (can be multiline)

 

詳細語法:見:https://developers.google.com/closure/templates/docs/commands

相關文章
相關標籤/搜索