(Quick Reference)

6.3.4 迭代标签 - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

6.3.4 迭代标签

Iterative tags are easy too, since you can invoke the body multiple times:

def repeat = { attrs, body ->
    attrs.times?.toInteger()?.times { num ->
        out << body(num)
    }
}

In this example we check for a times attribute and if it exists convert it to a number, then use Groovy's times method to iterate the specified number of times:

<g:repeat times="3">
<p>Repeat this 3 times! Current repeat = ${it}</p>
</g:repeat>

Notice how in this example we use the implicit it variable to refer to the current number. This works because when we invoked the body we passed in the current value inside the iteration:

out << body(num)

That value is then passed as the default variable it to the tag. However, if you have nested tags this can lead to conflicts, so you should should instead name the variables that the body uses:

def repeat = { attrs, body ->
    def var = attrs.var ?: "num"
    attrs.times?.toInteger()?.times { num ->
        out << body((var):num)
    }
}

Here we check if there is a var attribute and if there is use that as the name to pass into the body invocation on this line:

out << body((var):num)

Note the usage of the parenthesis around the variable name. If you omit these Groovy assumes you are using a String key and not referring to the variable itself.

Now we can change the usage of the tag as follows:

<g:repeat times="3" var="j">
<p>Repeat this 3 times! Current repeat = ${j}</p>
</g:repeat>

Notice how we use the var attribute to define the name of the variable j and then we are able to reference that variable within the body of the tag.

因为你可以多次调用主体(body),所以迭代标签也是很容易的:

def repeat = { attrs, body ->
    attrs.times?.toInteger()?.times { num ->
        out << body(num)
    }
}

在此例中,我们检查标签的times属性,如果存在呢,就将其转换为一个数字,然后使用Groovy的times方法来迭代给定的次数:

<g:repeat times="3">
<p>Repeat this 3 times! Current repeat = ${it}</p>
</g:repeat>

注意示例中,我们是如何使用隐式的it变量来引用当前的数字。此种方式是有效的,因为在迭代内部,我们将当前值传给了正在调用的主体(body):

out << body(num)

然后那个值作为缺省it变量传给了标签。但是,如果你有嵌套的标签的话,那么这将会导致冲突,因此你应该给给调用的主体变量命名:

def repeat = { attrs, body ->
    def var = attrs.var ?: "num"
    attrs.times?.toInteger()?.times { num ->
        out << body((var):num)
    }
}

此处我们检查是否存在一个var属性,如果有,那么将使用其值作为变量名称传递给正在调用的主体,如下所示:

out << body((var):num)

注意!变量名称两边的括号。如果你忽略它们,那么Groovy将会认为你正在使用一个String类型的键,而不是变量本身。

现在你可以修改标签的使用方法了,如下所示:

<g:repeat times="3" var="j">
<p>Repeat this 3 times! Current repeat = ${j}</p>
</g:repeat>

请注意我们是如何使用var属性来将变量名称定义为j,然后就可以在标签的主体内来引用此变量了。 tag.