Skip to content

17 解耦式模板逻辑

17.1 解耦逻辑:核心概念

到目前为止,我们为“虚拟杂货店”项目开发的模板都采用常规方式——将逻辑以属性的形式直接嵌入模板标记中。

但 Thymeleaf 还支持将模板标记与业务逻辑完全解耦,允许在 HTML 和 XML 模板模式下创建无任何逻辑的纯标记模板

其核心思路是:模板逻辑将定义在一个独立的逻辑文件中(更准确地说是“逻辑资源”,不一定是物理文件)。默认情况下,这个逻辑资源是与模板文件同目录、同名但后缀为 .th.xml 的文件:

/templates
+->/home.html    # 纯标记模板(无任何Thymeleaf代码)
+->/home.th.xml  # 独立的逻辑配置文件

因此 home.html 可以是完全无逻辑的,示例如下:

html
<!DOCTYPE html>
<html>
  <body>
    <table id="usersTable">
      <tr>
        <td class="username">Jeremy Grapefruit</td>
        <td class="usertype">Normal User</td>
      </tr>
      <tr>
        <td class="username">Alice Watermelon</td>
        <td class="usertype">Administrator</td>
      </tr>
    </table>
  </body>
</html>

这份文件里没有任何 Thymeleaf 代码——即便是不懂 Thymeleaf 或模板技术的设计师,也能创建、编辑或理解它;甚至可以直接复用外部系统提供的、不含任何 Thymeleaf 标记的 HTML 片段。

接下来,我们只需创建 home.th.xml 文件,就能把上述纯 HTML 模板转换成 Thymeleaf 模板:

xml
<?xml version="1.0"?>
<thlogic>
  <!-- 为id=usersTable的表格添加th:remove属性 -->
  <attr sel="#usersTable" th:remove="all-but-first">
    <!-- 为表格下第一个tr添加th:each遍历逻辑 -->
    <attr sel="/tr[0]" th:each="user : ${users}">
      <!-- 为tr下class=username的td添加文本渲染逻辑 -->
      <attr sel="td.username" th:text="${user.name}" />
      <!-- 为tr下class=usertype的td添加国际化文本渲染逻辑 -->
      <attr sel="td.usertype" th:text="#{|user.type.${user.type}|}" />
    </attr>
  </attr>
</thlogic>

在这段配置中可以看到:thlogic 块内包含多个 <attr> 标签,这些标签会根据自身 sel 属性(包含 Thymeleaf 标记选择器,底层是 AttoParser 选择器)选中原始模板中的节点,并为其注入 Thymeleaf 属性。

需要注意的是,<attr> 标签支持嵌套,嵌套后的选择器会自动拼接:

  • 外层 sel="#usersTable" + 内层 sel="/tr[0]" → 最终选择器为 sel="#usersTable/tr[0]"
  • 再嵌套 sel="td.username" → 最终选择器为 sel="#usersTable/tr[0]//td.username"

因此,上述两个文件合并后的效果,等价于直接在 home.html 中嵌入逻辑的写法:

html
<!DOCTYPE html>
<html>
  <body>
    <table id="usersTable" th:remove="all-but-first">
      <tr th:each="user : ${users}">
        <td class="username" th:text="${user.name}">Jeremy Grapefruit</td>
        <td class="usertype" th:text="#{|user.type.${user.type}|}">Normal User</td>
      </tr>
      <tr>
        <td class="username">Alice Watermelon</td>
        <td class="usertype">Administrator</td>
      </tr>
    </table>
  </body>
</html>

这种直接嵌入的写法更易读,也比拆分两个文件更简洁,但解耦式模板的核心优势在于:让模板完全独立于 Thymeleaf 逻辑,从设计视角来看可维护性大幅提升。

当然,设计和开发团队之间仍需约定一些规则(例如用户表格必须有 id="usersTable"),但在多数场景下,纯 HTML 模板能成为设计与开发团队之间更高效的协作载体。

总结

  1. 解耦式模板逻辑将 Thymeleaf 逻辑抽离到独立的 .th.xml 文件中,模板文件仅保留纯 HTML/XML 标记;
  2. .th.xml 通过 <attr> 标签的 sel 选择器定位模板节点,并注入 Thymeleaf 属性,支持嵌套选择器自动拼接;
  3. 解耦式模板的核心价值是实现“设计与开发分离”,纯 HTML 模板降低设计师的使用门槛,提升协作效率。