1

我有以下 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 ]
...

但如果宏是在另一个命名空间中定义的,则不会。

4

1 回答 1

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调用它。但是如果你把它叫做 form ,那么它将存在于宏的本地上下文中,它确实有自己的本地上下文。triggertrigger

为了让它工作......一种可能性是v通过 分配给命名空间范围的变量<#assign value = v>,然后value在解释的片段中引用。trigger如果可以的话,另一个解决方案当然是摆脱间接性。另一个解决方案是定义triggerwith?interpret而不是 with #macro,因为 thentrigger会看到v,所以也会看到hook

于 2013-09-06T11:30:39.453 回答