(A13)Tapestry Core :Component Rendering

本文翻译出处 http://tapestry.apache.org/tapestry5/tapestry-core/guide/rendering.html

本人翻译目的是用来学习Tapestry5的,共享出来希望大家批评指正。计划持续翻译。

chinajavawolf

 组件呈现

Tapestry4 方法
呈现是一个递归的过程。每一个组件实现了一个 render() 方法(从一个 Irender 接口继承)。组件将对其模板内的对象调用 render() 方法,包括其他的组件。
Bruce Tate 曾说“如果你有眩晕症,不要站在 JavaServer Faces 堆栈边向下看”这句话同样可以应用在 Tapestry4  。一旦你有很深的嵌套,循环组件,堆栈就会变得非常深。
Tapestry5 方法
组件呈现基于状态机和队列而不是尾递归。这打破了呈现在小块中处理,那样可以容易被实现或取代。不用担心,事实上,这只需要写非常少的代码。
呈现阶段
每个组件的呈现被分为许多阶段,如下图:
每个橙色的阶段( SetupRender, BeginRender, BeforeRenderBody, 等)与你类中一个或多个方法上放置的标注相对应。标注指示 Tapestry 调用你的方法作为那阶段的一部分。
被这些标住标记的方法被称为呈现阶段方法。
你的方法应该返回 void 或者返回一个 boolean 值。 返回值能够强制阶段被跳过 , 或者可以被重新访问 。在这个图里,实线显示的是正常的处理路径。当你的呈现阶段方法返回 false 而不是 true 或者 void 时,虚线代表的备用流将被触发。
呈现阶段方法可以不带参数,或者带一个 MarkupWriter 类型的参数。方法可以是你愿意的任何可见度,通常使用包级私有, 这样的可见度可以让你不用使组件方法为 public API 就可以测试你的代码( 同一个包 )。
这些方法是可选的,默认的行为是关联每一个阶段。
大部分反映组件混合 component mixins 的阶段也被加入到呈现阶段。 几个阶段几乎专为混合而存在。
一般,你的代码将用到 SetupRender, BeginRender, AfterRender CleanupRender 阶段,通常是这些阶段中的一个或两个。
下面是一个用来在两个值之间上下循环的组件源码,多次在他的 body 内呈现,并将当前的 index 值放入参数内。
  1. package org.example.app.components;   
  2.     
  3. import org.apache.tapestry.annotations.Parameter;   
  4. import org.apache.tapestry.annotations.AfterRender;   
  5. import org.apache.tapestry.annotations.SetupRender;   
  6.     
  7. public class Count   
  8. {   
  9.     @Parameter  
  10.     private int _start = 1;   
  11.     
  12.     @Parameter(required = true)   
  13.     private int _end;   
  14.     
  15.     @Parameter  
  16.     private int _value;   
  17.     
  18.     private boolean _increment;   
  19.     
  20.     @SetupRender  
  21.     void initializeValue()   
  22.     {   
  23.         _value = _start;   
  24.     
  25.         _increment = _start < _end;   
  26.     }   
  27.     
  28.     @AfterRender  
  29.     boolean next()   
  30.     {   
  31.         if (_increment)   
  32.         {   
  33.             int newValue = _value + 1;   
  34.     
  35.             if (newValue <= _end)   
  36.             {   
  37.                 _value = newValue;   
  38.                 return false;   
  39.             }   
  40.         }   
  41.         else  
  42.         {   
  43.             int newValue = _value - 1;   
  44.     
  45.             if (newValue >= _end)   
  46.             {   
  47.                 _value = newValue;   
  48.                 return false;    
  49.             }   
  50.         }   
  51.     
  52.         return true;   
  53.     }   
  54. }   
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 对于可见度,返回值和参数是灵活的。
使用这个机制,先前的例子可以被重写成:
  1. package org.example.app.components;   
  2.     
  3. import org.apache.tapestry.annotations.Parameter;   
  4.     
  5. public class Count   
  6. {   
  7.     @Parameter  
  8.     private int _start = 1;   
  9.     
  10.     @Parameter(required = true)   
  11.     private int _end;   
  12.     
  13.     @Parameter  
  14.     private int _value;   
  15.     
  16.     private boolean _increment;   
  17.     
  18.     void setupRender()   
  19.     {   
  20.         _value = _start;   
  21.     
  22.         _increment = _start < _end;   
  23.     }   
  24.     
  25.     boolean afterRender()   
  26.     {   
  27.         if (_increment)   
  28.         {   
  29.             int newValue = _value + 1;   
  30.     
  31.             if (newValue <= _end)   
  32.             {   
  33.                 _value = newValue;   
  34.                 return false;   
  35.             }   
  36.         }   
  37.         else  
  38.         {   
  39.             int newValue = _value - 1;   
  40.     
  41.             if (newValue >= _end)   
  42.             {   
  43.                 _value = newValue;   
  44.                 return false;    
  45.             }   
  46.         }   
  47.     
  48.         return true;   
  49.     }   
  50. }   
这样的风格是一种权衡 : 获利的一面是 , 代码更简单了简短了,方法名也是如此,在设计上是较为一致的 , 从一个类到另一个。 损失的一面就是名字是固定的 , 可能在某些情况下,要比标注方法描述的信息要少 (initializevalue() next() 看起来能描述处更多的信息 ).
你当然可以搭配使用,在某些场合使用特定的命名呈现阶段方法,在其他场合使用标注呈现阶段方法。
呈现组件
一个呈现阶段方法可以返回一个组件而不是返回 true false 。这个组件可能已被 Component 标注注入,或者已被作为一个参数传入。
无论如何,返回的组件将排在组件被被呈现之前,这个现行的组件继续呈现。
组件呈现甚至可以来自应用的一个完全不同的页面。
组件递归呈现是不允许的。
这个方法允许 Tapestry 页面的呈现是高度动态的。
返回组件实例不是祈祷的短路方法,返回 boolean 值的方法是。因为可能有多个方法可以返回组件(这是不推荐的 --- 错乱很快就会发生)。
方法冲突和排序
可能有多个方法被相同的呈现阶段标注。这包括同一个类中的方法,或者定义在一个类或者从其他类继承的混合方法。
  •   组件呈现前混合
当一个组件有 mixins, 时,那么混合呈现阶段方法在这个组件的呈现阶段方法前执行。如果一个混合扩展于基类,这个混合的父类方法在这个混合的子类呈现方法前执行。
混合中执行的顺序不能在当时被定义。
例外:被 MixinAfter 标注的混合排在组件之后,不是之前
  • 父类在子类之前
顺序始终是父类在前。在父类中定义的方法也总是在子类中定义的方法之前被调用。
  • 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,以避免对同一阶段的其他方法短路。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值