Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JSF2 Facelets中的JSTL。。。有道理吗?_Jsf_Jsf 2_Jstl_Facelets - Fatal编程技术网

JSF2 Facelets中的JSTL。。。有道理吗?

JSF2 Facelets中的JSTL。。。有道理吗?,jsf,jsf-2,jstl,facelets,Jsf,Jsf 2,Jstl,Facelets,我想有条件地输出一些Facelets代码 为此,JSTL标记似乎工作正常: <ui:repeat value="#{bean.products}" var="product"> <c:set var="price" value="#{product.price}" /> <h:outputText value="#{price}" /> </ui:repeat> ... 然而,我不确定这是否是一个最佳实践?还有其他方法可以实现

我想有条件地输出一些Facelets代码

为此,JSTL标记似乎工作正常:

<ui:repeat value="#{bean.products}" var="product">
    <c:set var="price" value="#{product.price}" />
    <h:outputText value="#{price}" />
</ui:repeat>

...
然而,我不确定这是否是一个最佳实践?还有其他方法可以实现我的目标吗?

使用

<h:panelGroup rendered="#{lpc.verbose}">
  ...
</h:panelGroup>

...
简介 JSTL
标记都是在视图构建时执行的,而JSF
标记都是在视图渲染时执行的

请注意,从JSF自己的
标记中,只有那些不从扩展的标记也是标记处理程序,例如
等。从
UIComponent
扩展的标记也是JSF UI组件,例如
,在视图构建期间,JSF UI组件中只有
id
binding
属性也会被评估。因此,下面关于JSTL生命周期的回答也适用于JSF组件的
id
binding
属性

视图构建时间是解析XHTML/JSP文件并将其转换为JSF组件树的时刻,该组件树随后存储为
FacesContext
UIViewRoot
。视图呈现时间是JSF组件树即将生成HTML的时刻,从
UIViewRoot\encodeAll()
开始。因此:JSF UI组件和JSTL标记并不像您从编码中期望的那样同步运行。您可以将其可视化如下:JSTL首先从上到下运行,生成JSF组件树,然后轮到JSF再次从上到下运行,生成HTML输出

vs
例如,此Facelets标记使用
在3个项目上迭代:


…在视图构建期间,在JSF组件树中创建三个独立的
组件,大致如下所示:


…在视图渲染期间,依次生成各自的HTML输出:

value1
价值2
价值3
请注意,您需要手动确保组件ID的唯一性,并且这些ID也会在视图构建期间进行评估

虽然此Facelets标记使用JSF UI组件
在3个项目上迭代:


…已经在JSF组件树中结束,在视图渲染期间,相同的
组件被重用,以基于当前迭代轮生成HTML输出:

value1
价值2
价值3
请注意,
作为
NamingContainer
组件,已经确保了基于迭代索引的客户端ID的唯一性;也不可能以这种方式在子组件的
id
属性中使用EL,因为它也在视图构建期间进行评估,而
{item}
仅在视图渲染期间可用。对于
h:dataTable
和类似组件也是如此

/
vs
渲染
作为另一个示例,此Facelets标记使用
有条件地添加不同的标记(您也可以为此使用
):

而此Facelets标记:

<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
它只适用于计算循环中的和。为此,请使用:

这将只评估一次,并在整个应用程序中作为
{dev}
提供

使用JSTL控制JSF组件树的构建 当在JSF迭代组件(如
等)中使用JSTL时,或者当JSTL标记属性依赖于JSF事件(如
preRenderView
或模型中提交的表单值)的结果时,使用JSTL可能只会导致意外的结果,而这些结果在视图构建时不可用。所以,只使用JSTL标记来控制JSF组件树构建的流程。使用JSF UI组件控制HTML输出生成的流程。不要将迭代JSF组件的
var
绑定到JSTL标记属性。不要依赖JSTL标记属性中的JSF事件

<> P> >您认为您需要通过<代码>绑定< /代码>将组件绑定到后台bean,或者通过代码> > FIDCAMDUTIN()/CODE获取一个组件,并在后台代码中使用java代码创建/操作它的子对象,代码为<代码>新的SOMeCo()/<代码>,而不是什么,那么您应该立即停止使用JSTL。由于JSTL也是基于XML的,因此动态创建JSF组件所需的代码将变得更易于阅读和维护

重要的是要知道,早于2.1.18的Mojarra版本在JSTL标记属性中引用视图范围的bean时,在部分状态保存中有一个bug。整个视图范围的bean将被重新创建,而不是从视图树中检索(只是因为在JSTL运行时完整的视图树还不可用)。如果您通过JSTL标记属性期望或存储视图范围bean中的某些状态,那么它将不会返回您期望的值,或者它将在构建视图树后恢复的真实视图范围bean中“丢失”。如果无法升级到Mojarra 2.1.18或更高版本,解决方法是在
web.xml
中关闭部分状态保存,如下所示:

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>
或者,如果您想有条件地构建(创建/添加)JSF组件,那么继续使用JSTL。这比在java中冗长地执行
newsomecomponent()
要好得多


...
另见:

对于开关式输出,您可以使用PrimeFaces Extensions中的面。

Thx,很好的答案。一般来说:JSTL标签仍然有意义吗?还是应该把它们看作是JSF 2以来的缩写?在大多数情况下,是的。但有时使用h:panelGroup是一个肮脏的解决方案,因为它会生成ta
<ui:repeat value="#{bean.products}" var="product">
    <c:set var="price" value="#{product.price}" />
    <h:outputText value="#{price}" />
</ui:repeat>
<ui:repeat value="#{bean.products}" var="product">
    ...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>