一、指令
if, else, elseif
语法
<#if condition> ... <#elseif condition2> ... <#elseif condition3> ... ... <#else> ... </#if>
用例
<#if x = 1> x is 1 </#if> <#if x = 1> x is 1 <#else> x is not 1 </#if>
switch, case, default, break
语法
<#switch value> <#case refValue1> ... <#break> <#case refValue2> ... <#break> ... <#case refValueN> ... <#break> <#default> ... </#switch>
字符串
<#switch being.size> <#case "small"> This will be processed if it is small <#break> <#case "medium"> This will be processed if it is medium <#break> <#case "large"> This will be processed if it is large <#break> <#default> This will be processed if it is neither </#switch>
数字
<#switch x> <#case x = 1> 1 <#case x = 2> 2 <#default> d </#switch>
如果x=1 输出 1 2, x=2输出 2, x=3 输出d
list, break
语法
<#list sequence as item> ... <#if item = "spring"><#break></#if> ... </#list>
关键字
item_index:是list当前值的下标
item_has_next:判断list是否还有值
用例
<#assign seq = ["winter", "spring", "summer", "autumn"]> <#list seq as x> ${x_index + 1}. ${x}<#if x_has_next>,</#if> </#list>
输出
1. winter,
2. spring,
3. summer,
4. autumn
include
语法
<#include filename> or <#include filename options>
options包含两个属性
encoding=”GBK” 编码格式
parse=true 是否作为ftl语法解析,默认是true,false就是以文本方式引入.注意在ftl文件里布尔值都是直接赋值的如parse=true,而不是parse=”true”
用例
/common/copyright.ftl包含内容
Copyright 2001-2002 ${me}<br> All rights reserved.
模板文件
<#assign me = "Juila Smith"> <h1>Some test</h1> <p>Yeah. <hr> <#include "/common/copyright.ftl" encoding=”GBK”>
输出结果
<h1>Some test</h1> <p>Yeah. <hr> Copyright 2001-2002 Juila Smith All rights reserved.
Import
语法
<#import path as hash>
类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件
用例
假设mylib.ftl里定义了宏copyright那么我们在其他模板页面里可以这样使用
<#import "/libs/mylib.ftl" as my> <@my.copyright date="1999-2002"/>
"my"在freemarker里被称作namespace
compress
语法
<#compress> ... </#compress>
用来压缩空白空间和空白的行
用例
<#assign x = " moo \n\n "> (<#compress> 1 2 3 4 5 ${moo} test only I said, test only </#compress>)
输出
(1 2 3 4 5 moo test only I said, test only)
escape, noescape
语法
<#escape identifier as expression> ... <#noescape>...</#noescape> ... </#escape>
用例
主要使用在相似的字符串变量输出,比如某一个模块的所有字符串输出都必须是html安全的,这个时候就可以使用该表达式
<#escape x as x?html> First name: ${firstName} <#noescape>Last name: ${lastName}</#noescape> Maiden name: ${maidenName} </#escape>
相同表达式
First name: ${firstName?html} Last name: ${lastName } Maiden name: ${maidenName?html}
assign
语法
<#assign name=value> or <#assign name1=value1 name2=value2 ... nameN=valueN> or <#assign same as above... in namespacehash> or <#assign name> capture this </#assign> or <#assign name in namespacehash> capture this </#assign>
用例
生成变量,并且给变量赋值
给seasons赋予序列值
<#assign seasons = ["winter", "spring", "summer", "autumn"]>
给变量test加1
<#assign test = test + 1>
给my namespage 赋予一个变量bgColor,下面可以通过my.bgColor来访问这个变量
<#import "/mylib.ftl" as my> <#assign bgColor="red" in my>
将一段输出的文本作为变量保存在x里
下面的阴影部分输出的文本将被赋值给x
<#assign x> <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n> ${n} </#list> </#assign> ${x}
上面的代码将产生如下输出:星期一 星期二 星期三 星期四 星期五 星期六 星期天
<#assign x>Hello ${user}!</#assign> error <#assign x=” Hello ${user}!”> true
同时也支持中文赋值,如:
<#assign 语法> java </#assign> ${语法}
打印输出:
java
global
语法
<#global name=value> or <#global name1=value1 name2=value2 ... nameN=valueN> or <#global name> capture this </#global>
全局赋值语法,利用这个语法给变量赋值,那么这个变量在所有的namespace中是可见的,如果这个变量被当前的assign语法覆盖 如<#global x=2> <#assign x=1> 在当前页面里x=2将被隐藏,或者通过${.global.x}来访问
setting
语法
<#setting name=value>
用来设置整个系统的一个环境
locale
number_format
boolean_format
date_format, time_format, datetime_format
time_zone
classic_compatible
用例
假如当前是匈牙利的设置,然后修改成美国
${1.2} <#setting locale="en_US"> ${1.2}
输出
1,2
1.2
因为匈牙利是采用“,”作为十进制的分隔符,美国是用“.”
macro, nested, return
语法
<#macro name param1 param2 ... paramN> ... <#nested loopvar1, loopvar2, ..., loopvarN> ... <#return> ... </#macro>
用例
<#macro test foo bar="Bar" baaz=-1> Test text, and the params: ${foo}, ${bar}, ${baaz} </#macro> <@test foo="a" bar="b" baaz=5*5-2/> <@test foo="a" bar="b"/> <@test foo="a" baaz=5*5-2/> <@test foo="a"/>
输出
Test text, and the params: a, b, 23 Test text, and the params: a, b, -1 Test text, and the params: a, Bar, 23 Test text, and the params: a, Bar, -1
定义循环输出的宏
<#macro list title items> <p>${title?cap_first}: <ul> <#list items as x> <li>${x?cap_first} </#list> </ul> </#macro> <@list items=["mouse", "elephant", "python"] title="Animals"/>
输出结果
<p>Animals: <ul> <li>Mouse <li>Elephant <li>Python </ul>
包含body的宏
<#macro repeat count> <#list 1..count as x> <#nested x, x/2, x==count> </#list> </#macro> <@repeat count=4 ; c halfc last> ${c}. ${halfc}<#if last> Last!</#if> </@repeat >
输出
1. 0.5
2. 1
3. 1.5
4. 2 Last!
t, lt, rt
语法
<#t> 去掉左右空白和回车换行 <#lt>去掉左边空白和回车换行 <#rt>去掉右边空白和回车换行 <#nt>取消上面的效果
当然 (指令还有很多)。
二、常用内建函数
内建函数很像子变量(如果了解Java术语的话,也可以说像方法), 它们并不是数据模型中的东西,是 FreeMarker 在数值上添加的。 为了清晰子变量是哪部分,使用 ?(问号)代替 .(点)来访问它们。常用内建函数的示例:
user?html 给出 user 的HTML转义版本, 比如 & 会由 & 来代替。
user?upper_case 给出 user 值的大写版本 (比如 "JOHN DOE" 来替代 "John Doe")
animal.name?cap_first 给出 animal.name 的首字母大写版本(比如 "Mouse" 来替代 "mouse")
user?length 给出 user 值中 字符的数量(对于 "John Doe" 来说就是8)
animals?size 给出 animals 序列中 项目 的个数(我们示例数据模型中是3个)
如果在 <#list animals as animal> 和对应的 </#list> 标签中:
animal?index 给出了在 animals 中基于0开始的 animal的索引值
animal?counter 也像 index, 但是给出的是基于1的索引值
animal?item_parity 基于当前计数的奇偶性,给出字符串 "odd" 或 "even"。在给不同行着色时非常有用,比如在 <td class="${animal?item_parity}Row">中。
一些内建函数需要参数来指定行为,比如:
animal.protected?string("Y", "N") 基于 animal.protected 的布尔值来返回字符串 "Y" 或 "N"。
animal?item_cycle('lightRow','darkRow') 是之前介绍的 item_parity 更为常用的变体形式。
fruits?join(", ") 通过连接所有项,将列表转换为字符串, 在每个项之间插入参数分隔符(比如 "orange,banana")
user?starts_with("J") 根据 user 的首字母是否是 "J" 返回布尔值true或false。
内建函数应用可以链式操作,比如user?upper_case?html 会先转换用户名到大写形式,之后再进行HTML转义。(这就像可以链式使用 .(点)一样)
可以阅读 全部内建函数参考。
三、快速浏览(备忘单)
这里给已经了解 FreeMarker 的人或有经验的程序员的提个醒:
直接指定值
字符串: "Foo" 或者 'Foo' 或者 "It's \"quoted\"" 或者 'It\'s "quoted"' 或者 r"C:\raw\string"
数字: 123.45
布尔值: true, false
序列: ["foo", "bar", 123.45]; 值域: 0..9, 0..<10 (或 0..!10), 0..
哈希表: {"name":"green mouse", "price":150}
检索变量
顶层变量: user
从哈希表中检索数据: user.name, user["name"]
从序列中检索数据: products[5]
特殊变量: .main
字符串操作
插值(或连接): "Hello ${user}!" (或 "Hello " + user + "!")
获取一个字符: name[0]
字符串切分: 包含结尾: name[0..4],不包含结尾: name[0..<5],基于长度(宽容处理): name[0..*5],去除开头: name[5..]
序列操作
连接: users + ["guest"]
序列切分:包含结尾: products[20..29], 不包含结尾: products[20..<30],基于长度(宽容处理): products[20..*10],去除开头: products[20..]
哈希表操作
连接: passwords + { "joe": "secret42" }
算术运算: (x * 1.5 + 10) / 2 - y % 100
比较运算: x == y, x != y, x < y, x > y, x >= y, x <= y, x lt y, x lte y, x gt y, x gte y, 等等。。。。。。
逻辑操作: !registered && (firstVisit || fromEurope)
内建函数: name?upper_case, path?ensure_starts_with('/')
方法调用: repeat("What", 3)
处理不存在的值:
默认值: name!"unknown" 或者 (user.name)!"unknown" 或者 name! 或者 (user.name)!
检测不存在的值: name?? 或者 (user.name)??
赋值操作: =, +=, -=, *=, /=, %=, ++, --
请参考: 运算符优先级
注意:本文归作者所有,未经作者允许,不得转载