我有以下freemarker模板:
[#local snippet ][#noparse]
[#assign out ]value: ${v}
[/#assign]
[/#noparse]
[/#local]
[#assign hook = snippet?interpret ]
...
[#macro trigger ]
[@hook /]
[/#macro]
...
[#list values as v ]
[@trigger ]
[/#list]
${out}
它本质上做的是定义一个钩子以便在稍后的某个时刻执行,一个宏来触发它的执行。
当我尝试渲染此模板时,出现以下错误:
The following has evaluated to null or missing:
==> v [in template "xxx.ftl->anonymous_interpreted" at line 1, column 17]
注意以下内容可能会很有趣:
[#list values as v ]
[@hook ]
[/#list]
只是工作,即按照我的预期渲染模板,为列表中的每个值打印value: xxx
。
我刚刚发现如果我通过常规宏代替解释片段,则不会发生错误:
[#assign hook = myMacro ]
...
但如果宏是在另一个名称空间中定义的话,则不行。
答案 0 :(得分:3)
循环变量(v
)基本上是#list
块的局部变量。因此,使用Java-ish伪代码,您尝试执行的操作就像:
void main() {
for (int v : values) {
trigger();
}
}
void trigger() {
print(v); // Error, v is not visible here!
}
在调用用?interpret
定义的指令时,这是特别的,因为它试图表现得像在调用位置复制粘贴代码片段一样。也就是说,使用@hook
调用的指令不会创建自己的本地上下文。因此,如果您从循环中直接将称为,它就会看到v
的原因。但是如果你将它称为trigger
形式,那么它将存在于trigger
宏的本地上下文中,它具有自己的本地上下文。
从使其工作为止......一种可能性是通过v
将<#assign value = v>
分配给命名空间范围变量,然后在解释的片段中引用value
。如果可以的话,另一种解决方案当然是摆脱trigger
间接。另一个解决方案是使用trigger
而不是?interpret
来定义#macro
,因为trigger
会看到v
,因此hook
也会{{1}}