模板片段

Carson Gross

模板片段是一种相对罕见的服务器端渲染 (SSR) 模板库功能,它允许您渲染模板中一个_片段_或部分内容,而不是整个模板。 这一功能在 超媒体驱动应用中非常实用,因为它允许您在内部分解特定视图以进行部分更新,而无需将模板的片段提取到单独的文件中进行渲染, 从而创建大量单独的模板文件。

通过将所有 HTML 保存在单个文件中,也更容易推理功能的工作方式。 这遵循了 行为局部性设计原则。

动机

让我们看看模板片段如何在一种名为 chill templates的 Java 模板语言中帮助我们构建 HDA。

这是一个简单的 chill 模板,/contacts/detail.html,用于显示联系人:

/contacts/detail.html
<html>
    <body>
        <div hx-target="this">
          #if contact.archived
          <button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
          #else
          <button hx-delete="/contacts/${contact.id}">Archive</button>
          #end
        </div>
        <h3>Contact</h3>
        <p>${contact.email}</p>
    </body>
</html>

在模板中,我们有一个归档功能,根据联系人的归档状态,我们要么显示“Archive” 按钮,要么显示“Unarchive”按钮,两者均由 htmx 驱动,并向不同的端点发出 HTTP 请求。

当我们点击显示的两个按钮中的任何一个时,我们希望用更新的按钮替换包围 按钮的 div 中的内容。 (注意 div 上的 hx-target="this",因此我们针对该 div 的 innerHTML 进行 替换。) 这将有效地在“Archive”和“Unarchive”之间来回切换。

现在,不幸的是,如果我们只想渲染按钮而不渲染此模板的其余部分,这通常涉及 将按钮拆分到自己的模板文件中并将其包含在此模板中,如下所示:

/contacts/detail.html
<html>
    <body>
        <div hx-target="this">
          #include archive-ui.html
        </div>
        <h3>Contact</h3>
        <p>${contact.email}</p>
    </body>
</html>
/contacts/archive-ui.html
#if contact.archived
<button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
#else
<button hx-delete="/contacts/${contact.id}">Archive</button>
#end

现在我们有两个模板。 我们现在可以单独渲染 archive-ui.html 模板,但这种拆分降低了 归档功能的可视性:当您只查看 detail.html 模板时,不太明显发生了什么。

当这种模板分解被推向极端时,可能会导致相当多的模板片段,这些片段总共变得难以管理和推理。

模板片段到救援

为了解决这个问题,chill templates 有一个 #fragment 指令。 此指令允许您指定模板中的一块 内容并仅渲染_那部分内容_:

使用片段的 /contacts/detail.html
<html>
    <body>
        <div hx-target="this">
          #fragment archive-ui
            #if contact.archived
            <button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
            #else
            <button hx-delete="/contacts/${contact.id}">Archive</button>
            #end
          #end
        </div>
        <h3>Contact</h3>
        <p>${contact.email}</p>
    </body>
</html>

在我们的模板中定义了这个片段后,我们现在可以渲染整个模板:

  Contact c = getContact();
  ChillTemplates.render("/contacts/detail.html", "contact", c);

或者我们也可以仅渲染模板的 archive-ui 片段

  Contact c = getContact();
  ChillTemplates.render("/contacts/detail.html#archive-ui", "contact", c);

当我们想要渲染联系人的整个详情页面时, 我们会使用第一个选项。

当我们处理归档/取消归档操作并希望仅重新渲染按钮时, 我们会使用第二个选项。

请注意,使用片段,我们能够将 UI 保存在单个文件中,并确切看到 功能发生了什么,而无需在不同的模板文件之间来回切换。 这提供了更清晰、更明显的 功能实现。

已知的模板片段实现

片段(以及在控制器中直接渲染它们的能力)似乎是模板库中相对罕见的功能,并为在使用 htmx 和其他 超媒体导向库时改善开发者体验提供了极好的机会。

以下是一些已知的片段概念实现:

如果您知道其他实现,请告诉我,以便我将其添加到此列表中。

</>