【问题标题】:<c:if> Tag does not reduce the component tree in composite components<c:if> 标签不会减少复合组件中的组件树
【发布时间】:2025-11-27 09:30:01
【问题描述】:

我们正在开发一个基于 Mojarra 2.2.8 的企业应用程序,该应用程序具有相当大且复杂的视图。我们最大的视图会生成超过 20.000 个节点的 JSF 组件树。当然,我们遇到了性能问题,因此我们开始通过将&lt;ui:repeat&gt; 替换为&lt;c:forEach&gt; 并将rendered 属性替换为&lt;c:if&gt; 块来减小树的大小,正如very informative post by BalusC 中所推荐的那样。 这些措施大大减少了组件树,并显着提高了性能。

但一项措施没有奏效:我们的视图在一个选项卡组中包含多个选项卡。当我们尝试通过&lt;c:if&gt;标签删除不可见标签的内容时,这些标签的组件树仍然存在,并且对性能没有任何好处。

我们发现,&lt;c:if&gt; 的这种用法与其他几个地方的唯一区别是,这次&lt;c:if&gt; 是复合组件的一部分,其内容是通过&lt;composite:insertChildren/&gt; 标签注入的。将复合组件标记的子代注入其定义的过程似乎与&lt;c:if&gt; 标记有某种冲突。我们还尝试用基于facet 的方法替换insertChildren 标签,但结果保持不变。

为了证明这一点,这里有一个复合组件,它将其所有内容包装在一个 &lt;c:if&gt; 标记中,其计算结果始终为 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。

【问题讨论】:

  • 试过更新的版本?试过我的脸吗?只是尝试,不是说在生产中使用

标签: jsf-2 jstl composite-component mojarra


【解决方案1】:

技术问题是此构造中的&lt;c:if&gt; 仅阻止包含(和执行)&lt;cc:insertChildren&gt; 标记本身。 &lt;cc:insertChildren&gt; 实际上负责重新定位任何复合组件子组件到复合组件实现中声明的位置,以便实际呈现它们。默认情况下,复合组件不呈现任何子组件。声明的子级实际上存储为复合组件的一个方面。

换句话说,&lt;c:if&gt; 实际上并不能阻止那些子组件最终出现在组件树中。它只会阻止&lt;cc:insertChildren&gt; 被调用。因此,观察到的行为按设计工作。要实现所需的行为,您实际上应该将 &lt;c:if&gt; 移回客户端。

<your:composite ...>
    <c:if test="#{false}">
        ...
    </c:if>
</your:composite>

我知道这是不直观的。实际上,您应该退后一步,不要使用复合组件来编写模板。他们不太适合这样做。您应该使用&lt;ui:composition&gt;&lt;ui:include&gt;&lt;ui:decorate&gt; 或标记文件来代替。复合组件只能用于组合组件。

另见:

【讨论】: