内联 注释和块 文本模板模式 12.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> 请注意,默认情况下,文本内联在标记中的每个标记的主体中都是活动的 - 而不是标记本身 - 因此我们无需执行任何操作即可启用它。 内联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> 12.2文字内联 文本内联与我们刚刚看到的表达内联功能非常相似,但它实际上增加了更多功能。必须明确启用它th:inline="text"。 文本内联不仅允许我们使用我们刚刚看到的相同内联表达式,而且实际上处理标签主体就好像它们是在TEXT模板模式下处理的模板一样,这允许我们执行基于文本的模板逻辑(不仅仅是输出表达式)。 我们将在下一章中看到有关文本模板模式的更多信息。 12.3 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库,如果存在,将使用它。如果没有,它将应用内置的序列化机制,涵盖大多数场景的需求并产生类似的结果(但不太灵活)。 12.4 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> 注释和块 文本模板模式