thymeleaf模板_Thymeleaf参考手册(十六):模板解耦逻辑

d0feeda77592650678c78b9e49fcc53c.png

解耦逻辑:概念

到目前为止,模板都是以正常的方式完成,逻辑以属性的形式插入模板中。

但是Thymeleaf还允许我们将模板标记与其逻辑完全分离,从而允许在 HTML XML 模板模式下创建完全无逻辑的标记模板

主要思想是模板逻辑将在单独的逻辑文件中定义(更确切地说是逻辑资源,因为它不必是file)。默认情况下,该逻辑资源将是与模板文件位于同一位置(例如,文件夹)的附加文件,其名称相同,但扩展名为 .th.xml

/templates
+->/home.html
+->/home.th.xml

因此,该 home.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.html 通过创建如下所示的其他 home.th.xml 文件,将该模板转换为Thymeleaf模板:

<?xml version="1.0"?>
<thlogic>
  <attr sel="#usersTable" th:remove="all-but-first">
    <attr sel="/tr[0]" th:each="user : ${users}">
      <attr sel="td.username" th:text="${user.name}" />
      <attr sel="td.usertype" th:text="#{|user.type.${user.type}|}" />
    </attr>
  </attr>
</thlogic>

在这里,我们可以看到一个 thlogic 块内有很多 <attr> 标签。这些 <attr> 标签对通过其属性选择的原始模板的节点执行属性注入,这些 sel 属性包含Thymeleaf标记选择器(实际上是AttoParser标记选择器)。

另请注意,<attr> 可以嵌套标签,以便附加选择器。例如,上述中的 sel="/tr[0]",将被处理为sel="#usersTable/tr[0]"。用户名的选择器 <td> 将被处理为 sel="#usersTable/tr[0]//td.username"

因此,一旦合并,上面看到的两个文件将与以下内容相同:

<!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,因此从设计的角度来看,它具有更好的可维护性。

当然,设计人员和开发人员之间仍然需要一些约定,例如,用户 <table> 将需要一个id="usersTable",但是在许多情况下,纯HTML模板将是设计团队和开发团队之间更好的沟通工具。

配置解耦模板

默认情况下,不会期望每个模板都需求解耦逻辑。相反,已配置的模板解析器(ITemplateResolver的实现)需要专门标记他们解析的模板为使用解耦逻辑。

除了StringTemplateResolver(不允许解耦逻辑)外,的所有其他现成 ITemplateResolver 实现都将提供一个useDecoupledLogic 标志,该标志将该解析器解析的所有模板标记为可能将其全部或部分逻辑存储在单独的资源中:

final ServletContextTemplateResolver templateResolver = 
        new ServletContextTemplateResolver(servletContext);
...
templateResolver.setUseDecoupledLogic(true);

混合耦合和解耦逻辑

启用后,解耦模板逻辑不是必需的。启用后,这意味着引擎将查找包含解耦逻辑的资源,如果存在,则将其解析并与原始模板合并。如果解耦的逻辑资源不存在,则不会引发任何错误。

同样,在同一模板中,我们可以混合使用耦合逻辑和解耦逻辑,例如,通过在原始模板文件中添加一些Thymeleaf属性,而将其他属性留给单独的解耦逻辑文件。最常见的情况是使用新的(在v3.0中)th:ref 属性。

th:ref属性

th:ref 只是标记属性。从处理的角度来看,它什么也没做,只是在处理模板后消失,但是它的作用在于它充当标记引用,即它可以像标记名或片段(th:fragment)一样通过标记选择器中的名称来解析。

因此,如果我们有一个选择器,例如:

<attr sel="whatever" .../>

这将匹配:

  • 任何 <whatever> 标签。
  • 具有 th:fragment="whatever" 属性的任何标签。
  • 具有 th:ref="whatever" 属性的任何标签。

例如,使用纯HTML id属性,使用 th:ref 的优势是什么?事实上,我们可能不想在标签中添加这么多 id 和 class 属性来充当逻辑锚,这可能会污染我们的输出。

从同样的意义上说,th:ref 的缺点是什么?很显然,我们会在模板中添加一些Thymeleaf逻辑(“逻辑”)。

请注意,th:ref 属性的适用性不仅适用于解耦的逻辑模板文件:它在其他类型的场景中也一样工作,例如在片段表达式(~{...})中。

解耦模板的性能影响

影响极小。当一个已解析的模板被标记为使用解耦逻辑并且不被缓存时,该模板逻辑资源将首先被解析,解析并处理为一系列内存中的指令:基本上是要注入到每个标记选择器的属性列表。

但这是唯一需要执行的附加步骤,因为在此之后,将解析真实模板,并且在解析这些模板时,由于AttoParser中节点选择的高级功能,这些属性将由解析器本身即时注入。。因此,已解析的节点将从解析器中出来,就像它们的注入属性写在原始模板文件中一样。

这样最大的优势?将模板配置为要缓存时,它将缓存已包含注入属性的模板。因此,一旦对高速缓存的模板使用解耦模板,其开销将绝对为零。

解耦逻辑的解析

Thymeleaf解析与每个模板相对应的解耦逻辑资源的方式可由用户配置。它由扩展点org.thymeleaf.templateparser.markup.decoupled.IDecoupledTemplateLogicResolver决定,并且为其提供了默认实现:StandardDecoupledTemplateLogicResolver

此标准实现有什么作用?

  • 首先,它将 prefix suffix 应用于模板资源的基本名称(通过其 ITemplateResource#getBaseName() 方法获得)。前缀和后缀都可以配置,默认情况下,前缀为空,后缀为 .th.xml
  • 其次,它要求模板资源通过其ITemplateResource#relative(String relativeLocation)方法来解析具有所计算名称的相对资源。

IDecoupledTemplateLogicResolver 可以 TemplateEngine 轻松配置要使用的具体实现:

final StandardDecoupledTemplateLogicResolver decoupledresolver = 
        new StandardDecoupledTemplateLogicResolver();
decoupledResolver.setPrefix("../viewlogic/");
...
templateEngine.setDecoupledTemplateLogicResolver(decoupledResolver);

我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!

如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!


文章不定时更新,可微信搜索「银河架构师」,精彩内容,先睹为快!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值