概要
<#macro name param1 param2 ... paramN>
...
<#nested loopvar1, loopvar2, ..., loopvarN>
...
<#return>
...
</#macro>
这里:
-
name: 宏变量的名称,它不是表达式。和 顶层变量 的语法相同,比如myMacro或my\-macro。 然而,它可以被写成字符串的形式,如果宏名称中包含保留字符时,这是很有用的, 比如<#macro "foo~bar">...。 注意这个字符串没有扩展插值(如"${foo}")。 -
param1,param2,等...: 局部变量 的名称,存储参数的值 (不是表达式),在=号后面和默认值(是表达式)是可选的。 默认值也可以是另外一个参数,比如<#macro section title label=title>。参数名称和 顶层变量 的语法相同,所以有相同的特性和限制。 -
paramN, 最后一个参数,可能会有三个点(...), 这就意味着宏接受可变数量的参数,不匹配其它参数的参数可以作为最后一个参数 (也被称作笼统参数)。当宏被命名参数调用,paramN将会是包含宏的所有未声明的键/值对的哈希表。当宏被位置参数调用,paramN将是额外参数的序列。 (在宏内部,要查找参数,可以使用myCatchAllParam?is_sequence。) -
loopvar1,loopvar2等...: 可选的,循环变量 的值, 是nested指令想为嵌套内容创建的。这些都是表达式。
return 和 nested
指令是可选的,而且可以在 <#macro
...> 和
</#macro> 之间被用在任意位置和任意次数。
没有默认值的参数必须在有默认值参数
(paramName=defaultValue)
之前。
描述
创建一个宏变量(在当前命名空间中,如果你知道命名空间的特性)。 如果你对宏和自定义指令不了解,你应该阅读 自定义指令指南。
宏变量存储模板片段(称为宏定义体)可以被用作 自定义指令。 这个变量也存储自定义指令的被允许的参数名。当你将这个变量作为指令时, 你必须给所有参数赋值,除了有默认值的参数。 默认值当且仅当你调用宏而不给参数赋值时起作用。
变量会在模板开始时被创建;而不管 macro
指令放置在模板的什么位置。因此,这样也可以:
<#-- call the macro; the macro variable is already created: --> <@test/> ... <#-- create the macro variable: --> <#macro test> Test text </#macro>
然而,如果宏定义被插在 include 指令中,
它们直到 FreeMarker 执行 include 指令时才会可用。
例如:没有参数的宏:
<#macro test> Test text </#macro> <#-- call the macro: --> <@test/>
将会输出:
Test text
示例:有参数的宏:
<#macro test foo bar baaz>
Test text, and the params: ${foo}, ${bar}, ${baaz}
</#macro>
<#-- call the macro: -->
<@test foo="a" bar="b" baaz=5*5-2/>将会输出:
Test text, and the params: a, b, 23
示例:有参数和默认值参数的宏:
<#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>
示例:支持多个参数和命名参数的宏:
<#macro img src extra...>
<img src="/context${src?html}"
<#list extra?keys as attr>
${attr}="${extra[attr]?html}"
</#list>
>
</#macro>
<@img src="/images/test.png" width=100 height=50 alt="Test"/>将会输出:
<img src="/context/images/test.png"
alt="Test"
height="50"
width="100"
>示例:支持多个位置参数的宏,不管是否使用命名或位置参数传递:
<#macro m a b ext...>
a = ${a}
b = ${b}
<#if ext?is_sequence>
<#list ext as e>
${e?index} = ${e}
</#list>
<#else>
<#list ext?keys as k>
${k} = ${ext[k]}
</#list>
</#if>
</#macro>
<@m 1 2 3 4 5 />
<@m a=1 b=2 c=3 d=4 e=5 data\-foo=6 myns\:bar=7 />将会输出:
a = 1
b = 2
0 = 3
1 = 4
2 = 5
a = 1
b = 2
c = 3
d = 4
e = 5
data-foo=6
myns:bar=7当前,命名的笼统参数是无序的,也就是说,不知道它们枚举时的顺序。 那么它们不会按相同传递顺序返回(上述示例输出相同的顺序只是为了理解)。
nested
nested 指令执行自定义指令开始和结束标签中间的模板片段。
嵌套的片段可以包含模板中任意合法的内容:插值,指令等...它在上下文环境中被执行,
也就是宏被调用的地方,而不是宏定义体的上下文中。因此,比如,
你不能看到嵌套部分的宏的局部变量。如果你没有调用 nested 指令,
自定义指令开始和结束标记中的部分将会被忽略。
比如:
<#macro do_twice> 1. <#nested> 2. <#nested> </#macro> <@do_twice>something</@do_twice>
将会输出:
1. something 2. something
nested 指令可以对嵌套内容创建循环变量。例如:
<#macro do_thrice>
<#nested 1>
<#nested 2>
<#nested 3>
</#macro>
<@do_thrice ; x>
${x} Anything.
</@do_thrice>将会输出:
1 Anything. 2 Anything. 3 Anything.
更为复杂的示例:
<#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!
return
使用 return 指令,
你可以在任意位置留下一个宏或函数定义。比如:
<#macro test> Test text <#return> Will not be printed. </#macro> <@test/>
将会输出:
Test text