【问题标题】:onShow event fires unnecessarily during each page reloadingonShow 事件在每次页面重新加载期间不必要地触发
【发布时间】:2026-01-18 05:30:01
【问题描述】:

我在使用 Primefaces 在我的项目中制作菜单时遇到问题。实际上,这个菜单将使我有可能显示一些带有工作区设置的小对话框(通过单击菜单项)。每个对话框都应该从数据库延迟加载数据。不幸的是,当我在页面中包含我的对话框(单个 xhtml 文件或带有 ui:include 的几个 xhtml 文件)时,每次重新加载页面时都会发生 onShow 事件,这是错误的,并会引发对数据库的过多不必要的请求。

这是一个例子:

界面部分

<h:form id="form1">
    <p:menubar id="mainMenu">
    <p:submenu label="Main menu" icon="ui-icon-document">
        <p:menuitem value="My settings" onclick="mySettingsWv.show()" url="#" />
    </p:submenu>
    </p:menubar>
</h:form>

<p:dialog id="mySettingsDlg" header="My Settings" widgetVar="mySettingsWv" resizable="false"
          closable="true" modal="true" showEffect="fade" hideEffect="explode" dynamic="true"
          closeOnEscape="true" onShow="#{mybean.onShow()}">
        <h:outputLabel value="Settings dialog" />
</p:dialog>

ManagedBean 部分:

@ManagedBean (name = "mybean")
@ViewScoped
public class MyBean {
   public static Logger log = Logger.getLogger(MyBean.class);

    public void onShow() {
       log.info("Method onShow is being called on each page reloading, but dialog still has not been shown");
     }
}

如果我对&lt;p:menuitem&gt; 使用“onclick”操作手动调用必要的方法,它仍然会在每次重新加载页面时执行它。此外,如果我尝试使用 actionListener,它的动作属性也不起作用。 &lt;p:ajax&gt; 不能附加到 &lt;p:menuitem&gt;

在这种情况下我该怎么办?我的代码有什么问题?

【问题讨论】:

  • 你可以将你的对话框包装在一个带有“渲染”属性的 div 中,这样它就不会显示在 dom 上,直到你真正想要它。并使用 ajax 调用来显示/隐藏它。你的问题是对话框总是显示在页面上,所以显示完成了。

标签: java jsf primefaces lazy-loading lazy-initialization


【解决方案1】:

查看 p:dialog 的 primefaces documentationp:menuitem 和 onclick 的问题相同)。那里的文档说onShow

客户端回调在显示对话框时执行。 (强调)

这意味着您可以在那里指定一个 javascript 函数,但是在每次显示对话框时都会调用 backingbean 上的操作。在您的情况下会发生以下情况: #{mybean.onShow()} 仅在解析文件时进行评估(即 p:dialog 呈现为 HTML),然后将方法返回的值插入其中(即空字符串)。

要解决这个问题,您必须定义一个在 bean 上进行调用的 javascript 回调。你可以使用p:remoteCommand

<p:remoteCommand name="onShow" action="#{mybean.onShow}"
      partialSubmit="true" process="@this"/>

然后将此回调指定为onShow 属性:

<p:dialog id="mySettingsDlg" ...
      onShow="onShow()">

【讨论】: