为了更好地理解 JSF (2.x) 中的 clientID 生成,有人可以向我解释一下 JSF 何时生成客户端 ID(哪个生命周期阶段、构建时间或渲染时间...)?
客户端 ID 将如何生成(如果提供/不提供组件 ID,则随机或使用特定逻辑...)?
为了更好地理解 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)
(如果有)将被要求将 clientId 转换为适合传输给客户端的形式。Renderer
此方法的返回值在实例的整个生命周期中必须是相同的值,除非组件的
属性发生更改,或者组件被放置在客户端 ID 发生变化的id
中(例如,NamingContainer
)。但是,即使在这些情况下,对此方法的连续调用也必须始终返回相同的值。实现必须遵循以下步骤来确定 clientId:UIData
在实现
NamingContainer
的视图层次结构中查找与this组件最接近的祖先。对其调用并将结果保存为getContainerClientId()
局部变量。在 thisparentId
组件上调用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()
方法上放置调试断点来跟踪逻辑。