模板片段

卡森·格罗斯

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

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

#动机

让我们看看模板片段如何在一种名为 chill 模板 的用于 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>

在模板中,我们有一个存档功能,根据联系人的存档状态,我们显示“存档”或“取消存档”按钮,这两个按钮都由 htmx 提供支持,并向不同的端点发出 HTTP 请求。

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

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

#/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 模板有一个 #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 和其他面向超媒体的库时改进开发人员体验提供了极好的机会。

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

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

</>