gpt4 book ai didi

jsf - 如何通过导航菜单ajax刷新动态包含内容? (JSF SPA)

转载 作者:行者123 更新时间:2023-12-02 19:15:13 25 4
gpt4 key购买 nike

我刚刚学习 JSF 2,感谢这个网站,我在这么短的时间内学到了很多东西。

我的问题是关于如何对所有 JSF 2 页面实现通用布局,并且每当我从不同面板单击链接/菜单时,仅刷新页面的内容部分而不是整个页面。我正在使用 Facelets 方法,它可以实现我想要的功能,只是每次我单击面板中的链接(例如左侧面板中的菜单项)时,整个页面都会刷新。我正在寻找一种仅刷新页面内容部分的方法。为了说明这一点,下面是我的目标页面布局。

enter image description here 没有发布我的代码,因为我不确定 Facelets 是否可以做到这一点。除了 Facelets 之外,还有其他方法更适合我的要求吗?

最佳答案

一个简单的方法是以下 View :

<h:panelGroup id="header" layout="block">
<h1>Header</h1>
</h:panelGroup>
<h:panelGroup id="menu" layout="block">
<h:form>
<f:ajax render=":content">
<ul>
<li><h:commandLink value="include1" action="#{bean.setPage('include1')}" /></li>
<li><h:commandLink value="include2" action="#{bean.setPage('include2')}" /></li>
<li><h:commandLink value="include3" action="#{bean.setPage('include3')}" /></li>
</ul>
</f:ajax>
</h:form>
</h:panelGroup>
<h:panelGroup id="content" layout="block">
<ui:include src="/WEB-INF/includes/#{bean.page}.xhtml" />
</h:panelGroup>

使用这个 bean:

@ManagedBean
@ViewScoped
public class Bean implements Serializable {

private String page;

@PostConstruct
public void init() {
page = "include1"; // Default include.
}

// +getter+setter.
}

在此示例中,实际包含模板为 include1.xhtml , include2.xhtmlinclude3.xhtml/WEB-INF/includes文件夹(文件夹和位置完全由您选择;文件只需放置在 /WEB-INF 中,以便通过猜测浏览器地址栏中的 URL 到达 prevent direct access)。

此方法适用于所有 MyFaces 2.x 版本,但对于 Mojarra 至少需要 2.3.x。如果您使用的 Mojarra 版本早于 2.3.0,那么当 <ui:include> 时,这一切都会失败。页面依次包含<h:form> 。任何回发都会失败,因为它完全丢失了 View 状态。您可以通过升级到最低 Mojarra 2.3.0 或使用此答案 h:commandButton/h:commandLink does not work on first click, works only on second click 中找到的脚本来解决此问题。 。或者,如果您已经在使用 PrimeFaces 并且专门使用 <p:xxx> ajax,那么它已经被透明地考虑在内。

此外,请确保您至少使用 Mojarra 2.1.18,因为旧版本将无法保持 View 作用域 bean 处于事件状态,从而导致在回发期间使用错误的包含。如果您无法升级,那么您需要退回到以下(相对笨拙)的有条件渲染 View 的方法,而不是有条件地构建 View :

...
<h:panelGroup id="content" layout="block">
<ui:fragment rendered="#{bean.page eq 'include1'}">
<ui:include src="include1.xhtml" />
</ui:fragment>
<ui:fragment rendered="#{bean.page eq 'include2'}">
<ui:include src="include2.xhtml" />
</ui:fragment>
<ui:fragment rendered="#{bean.page eq 'include3'}">
<ui:include src="include3.xhtml" />
</ui:fragment>
</h:panelGroup>

缺点是 View 会变得相对较大,并且所有关联的托管 bean 可能会被不必要地初始化,即使它们不会根据渲染条件使用。另请参阅JSTL in JSF2 Facelets... makes sense?有关 <ui:include src="#{...}"> 的深入解释与 <x:someComponent rendered="#{...}"> .

至于元素的定位,只需应用正确的 CSS 即可。这超出了 JSF 的范围:) 至少,<h:panelGroup layout="block">呈现 <div> ,所以这应该足够好了。

最后但并非最不重要的一点是,这种 SPA(单页应用程序)方法对 SEO 不友好。所有页面都不能被搜索机器人索引,也不能被最终用户添加书签,您可能需要在客户端中摆弄 HTML5 历史记录并提供服务器端后备。此外,对于带有表单的页面,将在所有页面中重用相同的 View 作用域 bean 实例,从而导致当您导航回以前访问过的页面时,作用域行为不直观。我建议采用模板方法,如本答案第二部分所述:How to include another XHTML in XHTML using JSF 2.0 Facelets?另请参阅How to navigate in JSF? How to make URL reflect current page (and not previous one) .

关于jsf - 如何通过导航菜单ajax刷新动态包含内容? (JSF SPA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7108668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com