Thymeleaf 内联
1. 表达内联
虽然标准方言允许我们使用标记属性来完成几乎所有操作,但在某些情况下我们可能更喜欢将表达式直接编写到HTML文本中。例如,我们可能更喜欢这样写:
<p>Hello, [[${session.user.name}]]!</p>
......而不是这个:
<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>
在Thymeleaf 之间表达[[...]]或被[(...)]认为是内联表达式,在其中我们可以使用任何类型的表达式,这些表达式在一个th:text或th:utext属性中也是有效的。
请注意,虽然[[...]]对应于th:text(即结果将被HTML转义),但[(...)]对应于th:utext并且不会执行任何HTML转义。所以对于一个变量,例如msg = 'This is great!',给定这个片段:
<p>The message is "[(${msg})]"</p>
结果将使这些标签不转义,因此:
<p>The message is "This is <b>great!</b>"</p>
而如果像以下一样逃脱:
<p>The message is "[[${msg}]]"</p>
结果将被HTML转义:
<p>The message is "This is <b>great!</b>"</p>
请注意,默认情况下,文本内联在标记中的每个标记的主体中都是活动的 - 而不是标记本身 - 因此我们无需执行任何操作即可启用它。
2. 内联vs自然模板
如果你来自其他模板引擎,其中这种输出文本的方式是常态,你可能会问:为什么我们从一开始就不这样做?它的代码少于所有这些 th:text 属性!
好吧,小心那里,因为尽管你可能会发现内联非常有趣,但是你应该永远记住,当你静态打开它们时,内联表达式将逐字显示在你的HTML文件中,所以你可能无法将它们用作设计原型了!
浏览器静态显示我们的代码片段而不使用内联的区别...
Hello, Sebastian!
......并使用它......
Hello, [[${session.user.name}]]!
......在设计实用性方面非常清楚。
禁用内联
但是,可以禁用此机制,因为实际上可能存在我们确实希望输出[[...]]或[(...)]序列而不将其内容作为表达式处理的情况。为此,我们将使用th:inline="none":
<p th:inline="none">A double array looks like this: [[1, 2, 3], [4, 5]]!</p>
这将导致:
<p>A double array looks like this: [[1, 2, 3], [4, 5]]!</p>
3. 文字内联
文本内联与我们刚刚看到的表达内联功能非常相似,但它实际上增加了更多功能。必须明确启用它th:inline="text"。
文本内联不仅允许我们使用我们刚刚看到的相同内联表达式,而且实际上处理标签主体就好像它们是在TEXT模板模式下处理的模板一样,这允许我们执行基于文本的模板逻辑(不仅仅是输出表达式)。
我们将在下一章中看到有关文本模板模式的更多信息。
4. JavaScript内联
JavaScript内联允许<script>
在HTML模板模式下处理的模板中更好地集成JavaScript 块。
与文本内联一样,这实际上相当于处理脚本内容,就好像它们是JAVASCRIPT模板模式中的模板一样,因此文本模板模式的所有功能(见下一章)都将在眼前。但是,在本节中,我们将重点介绍如何使用它将Thymeleaf表达式的输出添加到JavaScript块中。
必须使用th:inline="javascript"以下方式显式启用此模式:
<script th:inline="javascript"> ... var username = [[${session.user.name}]]; ... </script>
这将导致:
<script th:inline="javascript"> ... var username = "Sebastian \"Fruity\" Applejuice"; ... </script>
以上代码中需要注意的两件重要事项:
首先,JavaScript内联不仅会输出所需的文本,而且还会用引号和JavaScript来包含它 - 转义其内容,以便将表达式结果输出为格式良好的JavaScript文字。
其次,发生这种情况是因为我们将${session.user.name}表达式输出为转义,即使用双括号表达式:[[${session.user.name}]]。如果相反,我们使用非转义,如:
<script th:inline="javascript"> ... var username = [(${session.user.name})]; ... </script>
结果如下:
<script th:inline="javascript"> ... var username = Sebastian "Fruity" Applejuice; ... </script>
...这是一个格式错误的JavaScript代码。但是,如果我们通过附加内联表达式来构建脚本的一部分,那么输出未转义的内容可能就是我们所需要的,因此最好有这个工具。
JavaScript自然模板
所提到的JavaScript内联机制的智能远不止仅仅应用特定于JavaScript的转义并将表达式结果作为有效文字输出。
例如,我们可以在JavaScript注释中包装我们的(转义的)内联表达式,如:
<script th:inline="javascript"> ... var username = /*[[${session.user.name}]]*/ "Gertrud Kiwifruit"; ... </script>
并且Thymeleaf将忽略我们在注释之后和分号之前(在这种情况下'Gertrud Kiwifruit')编写的所有内容,因此执行此操作的结果将与我们不使用包装注释时完全相同:
<script th:inline="javascript"> ... var username = "Sebastian \"Fruity\" Applejuice"; ... </script>
但请仔细查看原始模板代码:
<script th:inline="javascript"> ... var username = /*[[${session.user.name}]]*/ "Gertrud Kiwifruit"; ... </script>
请注意这是有效的JavaScript代码。当您以静态方式打开模板文件时(无需在服务器上执行),它将完美执行。
所以我们这里有一个做自然模板的方法!
高级内联评估和JavaScript序列化
关于JavaScript内联的一个重要注意事项是,这种表达式评估是智能的,不仅限于字符串。Thymeleaf将在JavaScript语法中正确编写以下类型的对象:
- Strings
- Numbers
- Booleans
- Arrays
- Collections
- Maps
- Beans (objects with getter and setter methods)
例如,如果我们有以下代码:
<script th:inline="javascript"> ... var user = /*[[${session.user}]]*/ null; ... </script>
该${session.user}表达式将评估为一个User对象,Thymeleaf将正确地将其转换为Javascript语法:
<script th:inline="javascript"> ... var user = {"age":null,"firstName":"John","lastName":"Apricot", "name":"John Apricot","nationality":"Antarctica"}; ... </script>
这种JavaScript序列化的方式是通过org.thymeleaf.standard.serializer.IStandardJavaScriptSerializer接口的实现,可以StandardDialect在模板引擎使用的实例上配置。
此JS序列化机制的默认实现将在类路径中查找Jackson库,如果存在,将使用它。如果没有,它将应用内置的序列化机制,涵盖大多数场景的需求并产生类似的结果(但不太灵活)。
5. CSS内联
Thymeleaf还允许在CSS <style>
标签中使用内联,例如:
<style th:inline="css"> ... </style>
例如,假设我们将两个变量设置为两个不同的String值:
classname = 'main elems' align = 'center' 我们可以像以下一样使用它们:
<style th:inline="css"> .[[${classname}]] { text-align: [[${align}]]; } </style>
结果将是:
<style th:inline="css"> .main\ elems { text-align: center; } </style>
请注意CSS内联如何具有一些智能,就像JavaScript一样。具体来说,通过转义表达式输出的表达式[[${classname}]]将作为CSS标识符进行转义。这就是为什么我们classname = 'main elems'已经main\ elems在上面的代码片段中变成了原因。
高级功能:CSS自然模板等
与之前针对JavaScript解释的内容相同,CSS内联还允许我们的<style>
标记静态和动态地工作,即通过在注释中包装内联表达式作为CSS自然模板。看到:
<style th:inline="css"> .main\ elems { text-align: /*[[${align}]]*/ left; } </style>
下一章:Thymeleaf 文本模板模式
1. 文本语法在Thymeleaf的三种模板模式被认为是文字:TEXT,JAVASCRIPT和CSS。这使它们与标记模板模式区别开来:HTML和XML。文本模板模式与标记模式之间的关键区别在于,在文本模板中 ...