本文翻译出处 http://tapestry.apache.org/tapestry5/tapestry-core/guide/rendering.html
本人翻译目的是用来学习Tapestry5的,共享出来希望大家批评指正。计划持续翻译。
chinajavawolf
组件呈现
Tapestry4
方法
呈现是一个递归的过程。每一个组件实现了一个
render()
方法(从一个
Irender
接口继承)。组件将对其模板内的对象调用
render()
方法,包括其他的组件。
Bruce Tate
曾说“如果你有眩晕症,不要站在
JavaServer Faces
堆栈边向下看”这句话同样可以应用在
Tapestry4
。一旦你有很深的嵌套,循环组件,堆栈就会变得非常深。
Tapestry5
方法
组件呈现基于状态机和队列而不是尾递归。这打破了呈现在小块中处理,那样可以容易被实现或取代。不用担心,事实上,这只需要写非常少的代码。
呈现阶段
每个组件的呈现被分为许多阶段,如下图:
![](http://tapestry.apache.org/tapestry5/tapestry-core/images/component-render-states.png)
每个橙色的阶段(
SetupRender, BeginRender, BeforeRenderBody,
等)与你类中一个或多个方法上放置的标注相对应。标注指示
Tapestry
调用你的方法作为那阶段的一部分。
被这些标住标记的方法被称为呈现阶段方法。
你的方法应该返回
void
或者返回一个
boolean
值。
返回值能够强制阶段被跳过
,
或者可以被重新访问
。在这个图里,实线显示的是正常的处理路径。当你的呈现阶段方法返回
false
而不是
true
或者
void
时,虚线代表的备用流将被触发。
呈现阶段方法可以不带参数,或者带一个
MarkupWriter
类型的参数。方法可以是你愿意的任何可见度,通常使用包级私有,
这样的可见度可以让你不用使组件方法为
public API
就可以测试你的代码(
同一个包
)。
这些方法是可选的,默认的行为是关联每一个阶段。
一般,你的代码将用到
SetupRender, BeginRender, AfterRender
和
CleanupRender
阶段,通常是这些阶段中的一个或两个。
下面是一个用来在两个值之间上下循环的组件源码,多次在他的
body
内呈现,并将当前的
index
值放入参数内。
- package org.example.app.components;
- import org.apache.tapestry.annotations.Parameter;
- import org.apache.tapestry.annotations.AfterRender;
- import org.apache.tapestry.annotations.SetupRender;
- public class Count
- {
- @Parameter
- private int _start = 1;
- @Parameter(required = true)
- private int _end;
- @Parameter
- private int _value;
- private boolean _increment;
- @SetupRender
- void initializeValue()
- {
- _value = _start;
- _increment = _start < _end;
- }
- @AfterRender
- boolean next()
- {
- if (_increment)
- {
- int newValue = _value + 1;
- if (newValue <= _end)
- {
- _value = newValue;
- return false;
- }
- }
- else
- {
- int newValue = _value - 1;
- if (newValue >= _end)
- {
- _value = newValue;
- return false;
- }
- }
- return true;
- }
- }
从
next()
方法的
flase
值将引发
Tapestry
重新运行
BeginRender
阶段,并且从那里,重新呈现组件的
body(
这个组件没有模板
)
。返回
true
过渡到
CleanupRender
阶段。
注意 Tapestry 是如何适应你的方法的,可以通过标注记号,也可以根据叁数; 这里的两个被标注的方法没有执行任何的输出,因此他们不需要一个 MarkupWriter
真正兴奋的是模板和组件的
body
将常常包含更多的组件!这意味着很多不同的组件将在他们自己的状态机制的不同阶段。
-
SetupRender
这是一个你可以执行任何为你的组件呈现以前设置的地方。这是一个用来读组件参数和用他们设置临时实例变量的好地方。
-
BeginRender
对于组件这个呈现标签应该在开始标签处被呈现(闭合标签应该在
AterRender
阶段里被呈现)。组件同样能够防止模板或
body
由于返回
flase
被呈现。
组件可以有或没有一个模板。如果组件有模板,那么模板包括一个
< body >
元素,然后
BeforeRenderBody
阶段将被触发(让组件选择呈现还是不呈现他的
body
)。
如果组件模有
< body >
元素在模板里,那么
BeforeRenderBody
阶段不会被触发。
如果被
BeginRender
标注的方法,那么当这个阶段的时候没有特殊的输出方法。但是模板(如果存在)或
body
(如果当前没有模板,但是组件有
body
)将被呈现。
-
BeforeRenderTemplate
这个阶段是用来允许组件去修饰他的模板(在模板形成标签的周围创建标签)或者允许组件跳过他的模板的。
-
BeforeRenderBody
与组件
body
(组件充当容器模板的部分)相关的阶段。该
BeforeRenderBody
阶段是让组件的能够跳过
body,
同时还呈现组件模板的其余部分
(
如果有
).
如果没有方法被
BeforeRenderBody
标注,那么
body
将被默认呈现。当组件模板的
< body >
元素被展开时,这会再次发生,或者如果组件没有模板(但组件有
body
)时自动发生。
-
AfterRenderBody
AfterRenderBody
是
body
被呈现后执行的阶段;这只对组件的
body
发生。
-
AfterRender
这个阶段经常被用来呈现闭合标签以匹配
BeginRender
的起始标签。不管怎样,
AfterRender
阶段可以继续
CleanupRender
,或回退到
BeginRender
(就象上面的
Count
组件例子)。
如果没有方法被
AfterRender
标注,那么没有特殊的输出发生,然后
CleanupRender
阶段被触发。
-
CleanupRender
CleanupRender
是
SetupRender
的互补,他允许最后清除发生。
用方法名代替标注
如果你偏爱不用标注在你的方法上,你可通过为你的方法提供特定的名字这么做。需要的方法名是首字母小写的标注名:
setupRender(), beginRender(),
等。同标注呈现阶段方法一样,
Tapestry
对于可见度,返回值和参数是灵活的。
使用这个机制,先前的例子可以被重写成:
- package org.example.app.components;
- import org.apache.tapestry.annotations.Parameter;
- public class Count
- {
- @Parameter
- private int _start = 1;
- @Parameter(required = true)
- private int _end;
- @Parameter
- private int _value;
- private boolean _increment;
- void setupRender()
- {
- _value = _start;
- _increment = _start < _end;
- }
- boolean afterRender()
- {
- if (_increment)
- {
- int newValue = _value + 1;
- if (newValue <= _end)
- {
- _value = newValue;
- return false;
- }
- }
- else
- {
- int newValue = _value - 1;
- if (newValue >= _end)
- {
- _value = newValue;
- return false;
- }
- }
- return true;
- }
- }
这样的风格是一种权衡
:
获利的一面是
,
代码更简单了简短了,方法名也是如此,在设计上是较为一致的
,
从一个类到另一个。
损失的一面就是名字是固定的
,
可能在某些情况下,要比标注方法描述的信息要少
(initializevalue()
和
next()
看起来能描述处更多的信息
).
你当然可以搭配使用,在某些场合使用特定的命名呈现阶段方法,在其他场合使用标注呈现阶段方法。
呈现组件
无论如何,返回的组件将排在组件被被呈现之前,这个现行的组件继续呈现。
组件呈现甚至可以来自应用的一个完全不同的页面。
组件递归呈现是不允许的。
这个方法允许
Tapestry
页面的呈现是高度动态的。
返回组件实例不是祈祷的短路方法,返回
boolean
值的方法是。因为可能有多个方法可以返回组件(这是不推荐的
---
错乱很快就会发生)。
方法冲突和排序
可能有多个方法被相同的呈现阶段标注。这包括同一个类中的方法,或者定义在一个类或者从其他类继承的混合方法。
-
组件呈现前混合
混合中执行的顺序不能在当时被定义。
-
父类在子类之前
顺序始终是父类在前。在父类中定义的方法也总是在子类中定义的方法之前被调用。
-
对 AfterXXX 和 CleanupRender 倒序
AfterXXX
阶段是
BeginXXX
和
BeforeXXX
的配对补充。通常元素在一个较早的阶段开始然后元素被闭合在
AfterXXX阶段(在body和组件模板间呈现)。
In order to ensure that operations occur in the correct, and natural order, the render phase methods for these two stages are invoked in reverse order:
为了确保操作正确有序的方生,对于这两个时期的呈现阶段方法被倒序调用
1.
子类方法
2.
父类方法
3.
混合子类方法
4.
混合父类方法
-
在一个单一类内
目前
,
方法是按字母排序。有相同名字的方法通过参数数量排序
.
但即使这样
,
这也不是一个好主意
...
只定义一个方法
,
并且用它以你希望的顺序通知其他方法
.
-
短路
如果一个方法返回
ture
或
false
值,这将作短路处理。其他在这个阶段通常将被调用的方法将不被调用。
大多数呈现阶段方法将会返回void,以避免对同一阶段的其他方法短路。