JSF 中何时以及如何生成 clientID?

问题描述 投票:0回答:1

为了更好地理解 JSF (2.x) 中的 clientID 生成,有人可以向我解释一下 JSF 何时生成客户端 ID(哪个生命周期阶段、构建时间或渲染时间...)?

客户端 ID 将如何生成(如果提供/不提供组件 ID,则随机或使用特定逻辑...)?

jsf jsf-2 page-lifecycle clientid
1个回答
13
投票

为了更好地理解 JSF (2.x) 中的 clientID 生成,有人可以向我解释一下 JSF 何时生成客户端 ID(哪个生命周期阶段、构建时间或渲染时间...)?

它必须以 HTML 响应结束。因此它是在渲染响应期间生成的。如果您在

UIComponent#getClientId()
方法上放置调试断点,那么您将在堆栈中进一步看到(对于 Mojarra)
RenderResponsePhase#execute()
已被调用。当断点被命中时,这足以提示生命周期中的当前阶段。

客户端 ID 将如何生成(如果提供/不提供组件 ID,则随机或使用特定逻辑...)?

抽象

UIComponent#getClientId()
方法的具体实现可以在
UIComponentBase#getClientId()
中找到。 其源代码可以在 GitHub 上找到其 javadoc:

中描述了如何生成它

public abstract String getClientId(FacesContext context)

返回该组件的客户端标识符,必要时生成一个。关联的

Renderer
(如果有)将被要求将 clientId 转换为适合传输给客户端的形式。

此方法的返回值在实例的整个生命周期中必须是相同的值,除非组件的

id
属性发生更改,或者组件被放置在客户端 ID 发生变化的
NamingContainer
中(例如,
UIData
)。但是,即使在这些情况下,对此方法的连续调用也必须始终返回相同的值。实现必须遵循以下步骤来确定 clientId:

在实现 NamingContainer 的视图层次结构中查找与

this
组件最接近的祖先。对其调用
getContainerClientId()
并将结果保存为
parentId
局部变量。在 this
 组件上调用 
UIComponent.getId() 并将结果保存为
myId
局部变量。如果
myId
null
,则调用
context.getViewRoot().createUniqueId()
并将结果分配给
myId
。如果
parentId
是非
null
,则令
myId
等于
parentId + 
UINamingContainer.getSeparatorChar(jakarta.faces.context.FacesContext)
 + myId
。调用
Renderer.convertClientId(jakarta.faces.context.FacesContext, java.lang.String)
,传递
myId
,并返回结果。

很清楚,是吗?最重要的部分可能是记住实现

NamingContainer
的组件,从而在前面添加它们的客户端 ID。在标准 JSF 2.x 中,至少是
<h:form>
<h:dataTable>
<ui:repeat>
<f:subview>
<cc:implementation>
如果您轻轻地为所有组件指定一个固定 ID ,那么您还会在生成的 HTML 输出中看到该模式。

如果您没有为这些组件提供固定的 ID,则将使用 JSF 生成的 ID,该 ID 可以通过

UIViewRoot#createUniqueId()
获得(如上面的 javadoc 摘录中已经暗示的那样)。 它的 javadoc 说:

public String createUniqueId()

生成组件的标识符。该标识符将以

UNIQUE_ID_PREFIX
为前缀,并且在该 NamingContainer
 的非 
UIViewRoot
 子子树中是唯一的。

该前缀是

j_id
。实现如何生成它并没有明确,因此所有实现者都可以自由地实现它。他们通常使用树中组件计数的递增索引。因此,第一个组件
UIViewRoot
可以获得
j_id1
的 ID。它的第一个孩子可以获得
j_id2
的 ID。等等。您可以通过在
UIViewRoot#createUniqueId()
方法甚至
UIComponentBase#setId()
方法上放置调试断点来跟踪逻辑。

另请参阅:

© www.soinside.com 2019 - 2024. All rights reserved.