<c:if>标签不减少复合组件中的组件树
<c:if> Tag does not reduce the component tree in composite components
我们正在基于 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>
是复合组件的一部分,其内容是通过 <composite:insertChildren/>
标签。将复合组件标记的子标记注入其定义的过程似乎与 <c:if>
标记有某种冲突。我们还尝试用基于 facet
的方法替换 insertChildren
标签,但结果保持不变。
为了演示这一点,这里有一个复合组件,它将所有内容包装在一个 <c:if>
标记中,该标记始终计算为 false
:
<composite:interface>
</composite:interface>
<composite:implementation>
<c:if test="false">
<composite:insertChildren />
</c:if>
</composite:implementation>
此组件不应显示任何内容,即使它与视图中的许多子元素一起使用也是如此。它 什么都不显示,但组件树 仍然存在 并且没有性能优势。
不幸的是,这使我们无法开发性能优化的选项卡组复合组件。任何人都可以解释一下,为什么会发生这种情况以及是否有解决方法?
我们在 mojarra 2.2.8,el-api 2.2.5,tomcat 8.0.
技术问题是此构造中的 <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>
或标记文件。复合组件应该只用于组合一个组件。
另请参阅:
- When to use <ui:include>, tag files, composite components and/or custom components?
我们正在基于 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>
是复合组件的一部分,其内容是通过 <composite:insertChildren/>
标签。将复合组件标记的子标记注入其定义的过程似乎与 <c:if>
标记有某种冲突。我们还尝试用基于 facet
的方法替换 insertChildren
标签,但结果保持不变。
为了演示这一点,这里有一个复合组件,它将所有内容包装在一个 <c:if>
标记中,该标记始终计算为 false
:
<composite:interface>
</composite:interface>
<composite:implementation>
<c:if test="false">
<composite:insertChildren />
</c:if>
</composite:implementation>
此组件不应显示任何内容,即使它与视图中的许多子元素一起使用也是如此。它 什么都不显示,但组件树 仍然存在 并且没有性能优势。
不幸的是,这使我们无法开发性能优化的选项卡组复合组件。任何人都可以解释一下,为什么会发生这种情况以及是否有解决方法?
我们在 mojarra 2.2.8,el-api 2.2.5,tomcat 8.0.
技术问题是此构造中的 <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>
或标记文件。复合组件应该只用于组合一个组件。
另请参阅:
- When to use <ui:include>, tag files, composite components and/or custom components?