概要
<#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