我们正在开发一个基于Mojarra 2.2.8的具有相当大而复杂的视图的企业应用程序。我们最大的视图生成了> 20.000个节点的JSF组件树。我们遇到了性能问题,因此我们开始通过将<ui:repeat>
替换为<c:forEach>
并将rendered
属性替换为此<c:if>
块来减少树的大小very informative post by BalusC。
这些措施大大减少了组件树的数量,并显着提高了性能。
但有一项措施没有成功:我们的观点在标签组中包含多个标签。当我们尝试通过<c:if>
标记删除不可见标签的内容时,这些标签的组件树仍然存在,并且性能没有任何好处。
我们发现,<c:if>
与其他几个地方的使用之间的唯一区别是,这次<c:if>
是复合组件的一部分,其内容是通过{{1 }} 标签。将复合组件标记的子项注入其定义的过程似乎与<composite:insertChildren/>
标记有某种冲突。我们还尝试使用基于<c:if>
的方法替换insertChildren
标记,但结果保持不变。
为了证明这一点,这里有一个复合组件,它将所有内容包装在facet
标记中,始终评估为<c:if>
:
false
即使在视图中使用了很多子元素,该组件也不会显示任何内容。并且它 只显示组件树仍然存在并且没有性能优势。
不幸的是,这使得我们无法开发性能优化的选项卡组复合组件。任何人都可以解释,为什么会发生这种情况,如果有办法解决它?
我们在mojarra 2.2.8,el-api 2.2.5,tomcat 8.0。
答案 0 :(得分:3)
技术问题是此构造中的<c:if>
仅阻止<cc:insertChildren>
标记本身的包含(和执行)。 <cc:insertChildren>
实际上负责将重新定位任何复合组件子项负责到复合组件实现中声明的位置,以便实际呈现它们。默认情况下,复合组件不会呈现任何子项。声明的子节点实际上存储为复合组件的一个面。
换句话说,<c:if>
实际上并没有阻止那些组件子项在组件树中结束。它只会阻止调用<cc:insertChildren>
。因此观察到的行为按设计工作。为了实现所需的行为,您实际上应该将<c:if>
移回客户端。
<your:composite ...>
<c:if test="#{false}">
...
</c:if>
</your:composite>
我明白这是不直观的。实际上,您应该从使用复合组件退后一步来编写模板。它们并不适合它。您应该使用<ui:composition>
,<ui:include>
,<ui:decorate>
或标记文件。复合组件只应用于组成组件。