在使用<ui:composition>模板时,应该在哪里声明<f:metadata>?

25

我已经在将我的JSF应用程序转换为可书签页的页面方面取得了很大进展,但我想知道我是否正在正确地做。一个问题是,f:metadata标签最佳实践位置在哪里?

我的典型Facelets客户端页面如下所示:

    <ui:composition template="./pattern.xhtml">

        <ui:define name="content">

            <f:metadata>
                <f:viewParam name="userId" value="#{bean.userId}" />
                <f:viewParam name="startRecord" value="#{bean.startRecord}" />
                <f:viewParam name="pageSize" value="#{bean.pageSize}" />
                <f:viewParam name="sort" value="#{bean.sort}" />
            </f:metadata>

            <h1>Data Table</h1>

etc

所以在我的页面主体中遇到了 f:metadata 和子标签 f:viewParam。我的 pattern.xhtml 模板还有一个部分(名为"header"),可以将这些标签放在头部区域。它们应该放在那里吗?这样做有什么不同,或者我设置了一些尚未见过的副作用吗?

1个回答

44

从技术上讲,不论你在哪里在视图中声明<f:metadata>,只要它在顶层视图中(因此,在使用模板时,在模板客户端而不是主模板中),就没关系。当构建视图时,元数据基本上不是JSF组件树的一部分,而是视图根的一部分(您可以通过ViewDeclarationLanguage#getViewMetadata()方法按每个视图获取)。

最清晰的自文档化方法是将<f:metadata>放在视图顶部,这样您可以一眼看到任何元数据,无需滚动到视图源代码的中间或底部。

当使用纯页面时,请将其放置在<h:head>之前。

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    <f:metadata>
        <f:viewParam name="userId" value="#{bean.userId}" />
        <f:viewParam name="startRecord" value="#{bean.startRecord}" />
        <f:viewParam name="pageSize" value="#{bean.pageSize}" />
        <f:viewParam name="sort" value="#{bean.sort}" />
    </f:metadata>

    <h:head>
        ...
    </h:head>

    <h:body>
        ...
    </h:body>
</html>

使用模板时,如 <f:metadata> 标签文档中所述的推荐方式是,在主模板中声明一个单独的<ui:insert name="metadata">,并让客户端在<ui:define name="metadata">中定义<f:metadata>

<ui:composition template="/WEB-INF/pattern.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    <ui:define name="metadata">
        <f:metadata>
            <f:viewParam name="userId" value="#{bean.userId}" />
            <f:viewParam name="startRecord" value="#{bean.startRecord}" />
            <f:viewParam name="pageSize" value="#{bean.pageSize}" />
            <f:viewParam name="sort" value="#{bean.sort}" />
        </f:metadata>
    </ui:define>

    <ui:define name="content">
        <h1>Data Table</h1>
        ...
    </ui:define>
</ui:composition>

我必须说,这看起来比我一直在做的要干净一些。不知何故,我没有想到为元数据目的创建一个ui:insert,但现在我会了。 - AlanObject
这是否意味着无法将 f:metadata 放置在页面模板中以便使其可重用?那么,如果我们想在每个视图渲染之前执行一些操作,该怎么办呢? - Aritz
1
@Xtreme:只需使用<f:event>。它实际上不需要放置在<f:metadata>内部。另请参阅https://dev59.com/xVvUa4cB1Zd3GeqPpw8M#7343242 - BalusC
1
@BalusC,关于将其放置在<h:head>之前,相同的<f:metadata>标签文档说:“这必须是<f:view>的子代”。在顶层或其他地方隐式存在f:view吗? - Vsevolod Golovanov
2
@this:没错。它是UIViewRoot。另请参阅https://dev59.com/Lmox5IYBdhLWcg3w74q2 - BalusC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接