Velocity宏定义的坑与解决办法

简介:

使用Velocity,当然就免不了要使用宏,或者说使用Velocity而不使用其宏,就相当于废了Velocity一半以上的武功,非常可惜的。

怎么使用Velocity的宏呢,才最大程度的发挥其作用但是又避免掉入其中的坑呢?且听悠然乱弹乱弹:

官方文档中,关于Macro是这么说的:

#macro - Allows users to define a Velocimacro (VM), a repeated segment of a VTL template, as required

Format:

# [ { ] macro [ } ] ( vmname $arg1 [ $arg2 $arg3 ... $argn ] ) [ VM VTL code... ] # [ { ] #end [ } ]

  • vmname - Name used to call the VM (#vmname)
  • $arg1 $arg2 [ ... ] - Arguments to the VM. There can be any number of arguments, but the number used at invocation must match the number specified in the definition.
  • [ VM VTL code... ] - Any valid VTL code, anything you can put into a template, can be put into a VM.

Once defined, the VM is used like any other VTL directive in a template.

#vmname( $arg1 $arg2 )

当然,上面清晰的说明了怎么写Macro,

也就是说可以写成:

?
1
2
3
4
5
# {macro}(macroName $varName 1 $varName 2 )
 
## 这里是模板内容
 
# end
也可以写成
?
1
2
3
4
5
#macro(macroName $varName1 $varName2)
 
##这里是模板内容
 
#end
当然参数个数可以是0..n个。

OK,确实很简单,但是上面的说法实际上只解决了如何写出满足正确语法的宏,但是实际应用当中,如果不加以约束,可能就出现非常难以查找的问题。

比如下面定义了一个超链接的宏,由于id不是每次都用得到,因此id是可选参数,可以填,也可以不填:

?
1
2
3
#macro(link $href $id)
< a href = "$!href" #if($id) id = "$id" #end>$bodyContent</ a >
#end
然后,就可以如下使用了:
?
1
#@link("www.tinygroup.com")TinyGroup#end

上面的写法有问题么??似乎没有什么问题,即使什么参数也不传,只写下面的调用方法:

?
1
#@link()#end
渲染的结果也会是:
?
1
< a href = "" ></ a >
OK,如此说来,真的没有啥问题。

接下来,我们又要写一个图片链接的宏,同样的由于id不是每次都需要,我们把它写成可选的:

?
1
2
3
#macro(image $href $id)
< img src = "$href" #if($id) id = "$id" #end>
#end
在调用的时候,我们可以如下写:
?
1
#image("www.tinygroup.org/img/logo.gif")
也可以这样写
?
1
#image("www.tinygroup.org/img/logo.gif" "logoImage")
OK,一切都没有什么问题

但是我们想给首页上的Logo图片加个链接到首面上。

这个时候,我们会如下写:

?
1
2
3
#@link("www.tinygroup.org")
#image("www.tinygroup.org/img/logo.gif")
#end
渲染的结果也如我们所期望的
?
1
< a href = "www.tinygroup.org" >< img src = "www.tinygroup.org/img/logo.gif" ></ a >
确实也如我们期望,正确的渲染了。

这个时候,我们忽然期望首页链接添加个id,期望利用JQuery对其进行一些动态处理,我们就把代码写成下面的样子:

?
1
2
3
#@link("www.tinygroup.org" "homepageLink")
#image("www.tinygroup.org/img/logo.gif")
#end
这个时候,我们去执行的时候,忽然发现,程序不能正确运行了,去查看一下渲染的最终结果,居然是:
?
1
< a href = "www.tinygroup.org" id = "homepageLink" >< img src = "www.tinygroup.org/img/logo.gif"   id = "homepageLink" ></ a >
这说明一个道理就是:
  • 外层的宏中的变量,在内层的宏中是可以访问的
  • 内层中的变量,如果与外层中宏的变量名冲突,如果有传入,则按传入的值,如果没有传入,则取上层中的值

正是基于上述原因,在Tiny UI框架中,所有宏定义,宏变量都必须前宏前缀,也就是说上面的两个宏定义要按下面的方式来进行定义:

?
1
2
3
#macro(link $linkHref $linkId)
< a href = "$!linkHref" #if($linkId) id = "$linkId" #end>$bodyContent</ a >
#end
?
1
2
3
#macro(image $imageHref $imageId)
< img src = "$imageHref" #if($imageId) id="$imageId<span></ span >"#end>
#end

小结:

虽然原因及解决办法都非常简单,但是也是吃了亏之后才总结出来的,希望能对也使用Velocicty或其它模板语言的同学有帮助。

相关文章
|
2月前
|
C语言
BOOST1.75+QT5.15.2编译记录
本文记录了BOOST 1.75与Qt 5.15.2编译过程的详细步骤,包括编译结果截图、将boost源码编译为静态库的步骤,以及如何在Qt项目中使用BOOST库的测试代码。文章还提供了相关参考链接,以帮助解决在编译和使用过程中可能遇到的问题。
BOOST1.75+QT5.15.2编译记录
|
3月前
|
图形学
小功能⭐️Unity动态更改 Scripting Define Symbols (宏定义)
小功能⭐️Unity动态更改 Scripting Define Symbols (宏定义)
|
6月前
|
编译器
#define 宏定义看这一篇文章就够了
#define 宏定义看这一篇文章就够了
245 0
|
编译器 C语言
宏、条件编译(#ifdef)、#include(头文件包含)、#error和 #pragma的区别、#和##的含义和应用
宏、条件编译(#ifdef)、#include(头文件包含)、#error和 #pragma的区别、#和##的含义和应用
106 0
条件编译 #if #endif #if #elif #else #endif #ifdef #if define 的使用方法 引头文件#include<> 和#include““的区别
条件编译 #if #endif #if #elif #else #endif #ifdef #if define 的使用方法 引头文件#include<> 和#include““的区别
132 0
|
编译器 C++
Dev-c++中将头文件和头文件函数分离,编译主函数跳出undefined reference to 的问题解决
Dev-c++中将头文件和头文件函数分离,编译主函数跳出undefined reference to 的问题解决
Dev-c++中将头文件和头文件函数分离,编译主函数跳出undefined reference to 的问题解决
|
C++
C++学习003-#define 自定义宏
C++中可以用#define来定义自定义的宏 也可以用使用#define来定义常量
97 0
Confluence 6 使用 Velocity 宏
当编辑自定义 Decorator 模板文件的时候,有一些宏可被用来定义页面中复杂或者多变的内容,例如菜单,链接等。你可以插入这些宏到你的模板中。
1020 0