我有一个像这样的简单自定义组件,它不尊重呈现的属性。
@FacesComponent("my.OutputText")
public class OutputText extends UIPanel
{
@Override public void encodeBegin(FacesContext context) throws IOException {...}
@Override public void encodeEnd(FacesContext context) throws IOException {...}
}
当然,我可以在两种方法中检查渲染的属性,添加@Override public boolean getRendersChildren()
,还可以检查rendered的attribute,然后简单地不在encodeChildren
中渲染子级。
但是,实现这个通用特性的推荐规则是什么?
这已经在UIComponent
类的javadoc中描述过了。
以encodeBegin()
方法为例:
encodeBegin
public abstract void encodeBegin(FacesContext context) throws java.io.IOException
如果我们的
rendered
属性是true
,则将此UIComponent
的当前状态的开头呈现给指定FacesContext中包含的响应。致电pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent)
。调用Application.publishEvent(javax.faces.context.FacesContext, java.lang.Class, java.lang.Object)
,传递PreRenderComponentEvent
.class
作为第一个参数,传递要呈现的组件实例作为第二个参数。如果
Renderer
与该UIComponent
相关联,则实际编码将被委托给Renderer#encodeBegin(FacesContext, UIComponent)
。如果我们的渲染属性是
false
,请调用pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent)
并立即返回。
和getRendersChildren()
方法:
getRendersChildren
public abstract boolean getRendersChildren()
返回一个标志,指示此组件是否负责呈现其子组件。
UIComponentBase#getRendersChildren
中的默认实现试图找到该组件的渲染器。如果是,则调用Renderer#getRendersChildren
并返回结果。如果没有,则返回false
。从JavaServer Faces规范的1.2版本开始,鼓励组件作者从该方法返回true
并依赖UIComponentBase#encodeChildren
。
注意最后一句话。这是UIComponent#encodeChildren()
的一个:
encodeChildren
public abstract void encodeChildren(FacesContext context) throws java.io.IOException
如果我们的
rendered
属性是true
,则呈现此UIComponent
的子UIComponents
。只有当rendersChildren
属性为true
时,才会调用此方法。如果
Renderer
与该UIComponent
相关联,则实际编码将被委托给Renderer#encodeChildren(FacesContext, UIComponent)
。如果没有任何Renderer
与此UIComponent
相关联,则遍历此组件的每个子级并调用encodeAll(javax.faces.context.FacesContext)
。
请注意,UIComponentBase
已经实现了它们。如果您已经重写了一个方法,那么您需要遵循完全相同的规则,或者如果可能的话,可以使用super.encodeXxx()
。如果您没有覆盖encodeChildren()
,那么无论如何都不需要这样做。