<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?