Skip to content

13 文本模板模式

13.1 文本语法

Thymeleaf 中有三种被归为文本模板模式的类型:TEXTJAVASCRIPTCSS,它们与「标记型模板模式」(HTMLXML)有着本质区别。

文本模板模式和标记型模式的核心差异在于:文本模板中没有可承载属性式逻辑的标签(比如 HTML 里的 th:each 写在 <div> 上),因此必须通过其他机制来嵌入模板逻辑。

这些机制里最基础、最核心的就是内联(inlining)(我们在上一章已详细讲解)。内联语法是文本模板模式下输出表达式结果的最简方式,比如下面这段纯文本邮件模板:

text
  Dear [(${name})],

  Please find attached the results of the report you requested
  with name "[(${report.name})]".

  Sincerely,
    The Reporter.

即便没有任何标签,也是一个完整且可在 TEXT 模式下执行的 Thymeleaf 模板。

但如果需要编写比「单纯输出表达式」更复杂的逻辑(比如遍历、条件判断),就需要一种全新的、不依赖标签的语法:

text
[# th:each="item : ${items}"]
  - [(${item})]
[/]

这其实是以下冗长写法的精简版本:

text
[#th:block th:each="item : ${items}"]
  - [#th:block th:utext="${item}" /]
[/th:block]

这种新语法基于「可处理元素」设计,但不再用 <element ...> 声明,而是采用 [#element ...] 格式。元素声明:以 [#元素名 ...] 开头,以 [/元素名] 结尾(如 [#th:block ...] ... [/th:block]);自闭合元素:类似 XML 语法,在开头元素后加 / 表示独立标签(如 [#th:block th:utext="${item}" /])。

标准方言只包含其中一个元素的处理器:即我们已经熟悉的 th:block,不过我们也可以在自己的方言中对其进行扩展,并以常规方式创建新的元素。此外,th:block 元素([#th:block ...] ... [/th:block])允许缩写为空字符串形式([# ...] ... [/]),因此上面的代码块实际上等价于:

text
[# th:each="item : ${items}"]
  - [# th:utext="${item}" /]
[/]

[# th:utext="${item}" /] 等价于不转义的内联表达式 [(${item})],我们完全可以使用这种写法来精简代码。最终我们就得到了开头看到的第一段代码片段:

text
[# th:each="item : ${items}"]
  - [(${item})]
[/]

需要注意的是,文本语法要求「元素完全闭合」(无未闭合标签)、「属性值加引号」,整体更贴近 XML 风格,而非宽松的 HTML 风格。

我们来看一个更完整的 TEXT 模板示例 —— 一份纯文本邮件模板:

text
Dear [(${customer.name})],

This is the list of our products:

[# th:each="prod : ${products}"]
   - [(${prod.name})]. Price: [(${prod.price})] EUR/kg
[/]

Thanks,
  The Thymeleaf Shop

执行后输出结果:

text
Dear Mary Ann Blueberry,

This is the list of our products:

   - Apricots. Price: 1.12 EUR/kg
   - Bananas. Price: 1.78 EUR/kg
   - Apples. Price: 0.85 EUR/kg
   - Watermelon. Price: 1.91 EUR/kg

Thanks,
  The Thymeleaf Shop

再来看一个 JAVASCRIPT 模板模式 的示例:一个名为 greeter.js 的文件。我们将其作为文本模板处理,处理后的结果可在 HTML 页面中调用。需要注意的是,这并非 HTML 模板中的 <script> 代码块,而是一个独立作为模板被处理的 .js 文件:

javascript
var greeter = function() {

    var username = [[${session.user.name}]];

    [# th:each="salut : ${salutations}"]    
      alert([[${salut}]] + " " + username);
    [/]

};

执行后输出结果:

javascript
var greeter = function() {

    var username = "Bertrand \"Crunchy\" Pear";

      alert("Hello" + " " + username);
      alert("Ol\u00E1" + " " + username);
      alert("Hola" + " " + username);

};

总结

  1. 文本模板模式(TEXT/JAVASCRIPT/CSS)无标签承载逻辑,需通过内联或 [# ...] 语法实现复杂逻辑;
  2. [# 指令] ... [/]th:block 的缩写,是文本模板中实现遍历/条件等逻辑的核心语法;
  3. 文本语法要求元素闭合、属性加引号,风格更贴近 XML;
  4. 可直接处理独立的 .txt/.js/.css 文件,无需嵌套在 HTML 中,拓展了 Thymeleaf 的适用场景。