#macro 指令让模板设计者可以将些重复、相关的的脚本判断定义为一个功能块.无论在什么情况下. 出于单一意图设计的 Velocimacro都会最大程序的减少模板编写中可以的出错,还是看个例子来理解一下Velocimacros的概念.
#macro( d )
<tr><td></td></tr>
#end
这样就定义了一个名为d的宏,它可以在其它的模板中像下面那样直接引用:
#d()
Velocimacro可以接收0到任意多的传入参数.如上个例是0个参数,但当它被调用时,也必须传入同样多的参数. 这里定义了一个有两个参数的宏.
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
然后,我们在页面中来使用:
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>
注意变量 $greatlakes 取代了宏中变量 $somelist的输出,最终的输出如下:
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
宏一般被定义在模板中,那么站点上的其它模板中又如何调用呢?如能定义一个可以更大范围内共想的宏就太好了
如果将宏#tablerows($color $list) 定义到一个模板库中(Velocimacros template library), 其它模板就都可以访问它了.
Velocimacro Arguments(宏的参数)
Velocimacros可以从TVL中接受以下参数 :
· 引用类型 : 所有以'$'开头的
· String literal : something like "$foo" or 'hello'
· Number literal : 1, 2 etc
· IntegerRange : [ 1..2] or [$foo .. $bar]
· ObjectArray : [ "a", "b", "c"]
· boolean value true
· boolean value false
当传一个引用参数给宏时, 引用是通过名字传入的('pass by name').
#macro( callme $a )
$a $a $a
#end
#callme( $foo.bar() )
上例中命令 bar() 被调用了3 times.
最后要说的是,这个特性有些难以学习,但当你精心组织规划你的宏库时, 消除在VTL中重复功能的脚本时 –你可以像使用一个对象或组件一样使用宏, 比如一个宏对象生成多个表格的重复色彩.
如果你想利用这个特性,你只需要像下面那样简单的编码传一个值给它来调用 :
#set( $myval = $foo.bar() )
#callme( $myval )
Velocimacro Properties(宏的属性)
配置文件 velocity.properties 中有多行相关配置,具体请见《Velocity Java开发指南中文版》.
velocimacro.library –用来指定全局的宏库,多个可以,号分开.
velocimacro.permissions.allow.inline – 默认为true,可以让宏定义在一个正规的模板文件中.
velocimacro.permissions.allow.inline.to.replace.global – 用来指定模板内定义的宏的功能是否要以替换全局库,默认为false.
velocimacro.permissions.allow.inline.local.scope –模板中定义的宏的使用范围是否只是本模板可用.
velocimacro.context.localscope –如果为true,宏通过#set赋值时.宏中将保持一个,且不会由于context中的数据被修改而变化,同样,宏中的修改也不会改变context中的。
velocimacro.library.autoreload – 是否自动重新载入,用于调试环境,默认false,如为true,需要取掉chcheing:. file.resource.loader.cache = false ).
一些细节:
宏必须在模板中使用#macro()指令前定义.
尽量不要直接在模板中使用#parse() 包含 #macro() 指令.因为 #parse() 动作在运行执行,时会有一个在VM中查找元素的过程.
这是一些简短的问题总结,也许你先要有这样一个概念:. 'Velocimacro' 就像一个‘VM’。
可否用一个指示符做为另外一个指示符运算的参数?
如 : #center( #bold("hello") )
No. 指示符不是有效的参数但你可以这样实现你想要的:
#set($stuff = "#bold('hello')" )
#center( $stuff )
或者:
#center( "#bold( 'hello' )" )
上面这个例子中,参数是在调用的宏中生成的.不是调用者传入的. 看看下面的例子 :
#macro( inner $foo )
inner : $foo
#end
#macro( outer $foo )
#set($bar = "outerlala")
outer : $foo
#end
#set($bar = 'calltimelala')
#outer( "#inner($bar)" )
输出将是:
Outer : inner : outerlala
因为 "#inner($bar)" 是发生在 #outer()内部的!
可否通过 #parse()来注册一个宏 ?
宏必须在模板使用前定义好.前面己有一个关于此问题的建议,#parse()是运行时执进的,JVM查找对象的顺序不一定会全按我们预计的执行。
什么是宏的自动重新装载?
这是由配置参数决定的, 为方例开发者,在生产环境中则不需要 :
velocimacro.library.autoreload
默认的是false.当设为true中,需要设定chcheing参数;
<type>.resource.loader.cache = false
(具体配置请见开发指南,如下是一个配置的例子)
file.resource.loader.path = templates
file.resource.loader.cache = false
velocimacro.library.autoreload = true
注意:Don't keep this on in production.