Thymeleaf(第五/六/七章)设置属性值/迭代/条件计算

技术文章 10个月前 完美者
1,335 0

标签:log   相等   代码   for   lang   规则   选项   null   each   

提示:文章代码可左右滑动

5 设置属性值

5.1 设置任何属性的值

使用th:attr属性,它有能力改变标签的属性值:

1<form action="subscribe.html" th:attr="action=@{/subscribe}">
2  <fieldset>
3    <input type="text" name="email" />
4    <input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
5  </fieldset>
6</form>

th:attr的概念非常直接,简单地使用一个表达式把一个值赋给一个属性,上面示例的结果:

1<form action="/gtvg/subscribe">
2  <fieldset>
3    <input type="text" name="email" />
4    <input type="submit" value="?Suscríbe!"/>
5  </fieldset>
6</form>

但是一次设置多个属性值该如何做,XML的规则不允许你在一个标签里设置一个属性两次,因此th:attr将采用一个逗号分割的赋值列表,如:

1<img src="../../images/gtvglogo.png" 
2     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

它将产生如下输出:

1<img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />

5.2 设置特定属性的值

此时此刻,你可能认为像这样:

1<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>

这种方式十分丑陋,虽然实践性很强,但不够优雅。

thymeleaf也同意你的看法,因此th:attr几乎不使用。通常,你将使用其它的th:*属性,它的任务是设置具体的标签属性。
例如,设置value属性,使用th:value:

1<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>

这看起来更好些。让我们再设置下form标签的action属性:

1<form action="subscribe.html" th:action="@{/subscribe}">

你还记的th:href属性吗,它们是完全相同的类型:

1<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>

有很多像这样的属性,它们分别对应HTML5的具体属性,参考官网:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes

5.3 一次设置多个值

有两个十分特殊的属性叫做th:alt-title和th:lang-xmllang,可以使用相同的值一次设置两个属性。
th:alt-title将设置alt和title
th:lang-xmllang将设置lang和xml:lang
其实可以替换为下面这样:

1<img src="../../images/gtvglogo.png" 
2     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

或者这样,也是相同的:

1<img src="../../images/gtvglogo.png" 
2     th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />

本来是这样的:

1<img src="../../images/gtvglogo.png" 
2     th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" />

5.4 从后面和前面追加

thymeleaf也提供了th:attrappend和th:attrprepend属性,可以为已存在的属性值追加后缀或前缀。
如追加CSS类:

1<input type="button" value="Do it!" class="btn" th:attrappend="class=${‘ ‘ + cssStyle}" />

如果cssStyle变量的值是warning,你将得到:

1<input type="button" value="Do it!" class="btn warning" />

在标准的方言里有两个特别的追加属性,th:classappend和th:styleappend属性,用于添加CSS类或一个样式片段到一个元素而不重写现有的:

1<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? ‘odd‘">

5.5 固定值布尔属性

HTML有布尔属性的概念,这种属性没有值,只要它出现了就意味着值是true。在XHTML中,这些属性只会有一个值,那就是它自己。
例如,checked:

1<input type="checkbox" name="option2" checked /> <!-- HTML -->
2<input type="checkbox" name="option1" checked="checked" /> <!-- XHTML -->

标准的方言包含这样的属性,允许你通过计算一个条件来设置它们,如果为true,属性将被设置为它的固定值。如果为false,属性将不被设置:

1<input type="checkbox" name="active" th:checked="${user.active}" />

标准方言中还存在其它这样的属性,参考官网:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#fixed-value-boolean-attributes

5.6 设置任何属性的值(默认属性处理器)

thymeleaf提供一个默认属性处理器,允许我们设置任何属性的值,即使没有具体的th:*处理器被定义在标准方言里。
一些看起来像:

1<span th:whatever="${user.name}">...</span>

将导致成这样:

1<span whatever="John Apricot">...</span>

5.7 支持HTML5友好的属性和元素名称

在一个更加HTML5友好的方式里,可以使用一个完全不同的语法来应用处理器到你的模板。

1<table>
2    <tr data-th-each="user : ${users}">
3        <td data-th-text="${user.login}">...</td>
4        <td data-th-text="${user.name}">...</td>
5    </tr>
6</table>

data-{prefix}-{name}语法是HTML5中写自定义属性的标准方式,不要求开发者使用任何命名空间名称像th:*。thymeleaf使这种语法对于你的所有方言自动可用(不仅是标准方言)。

也有一个语法来指定自定义标签,{prefix}-{name},它遵从W3C自定义元素规范。这可以被使用,例如,th:block元素,也是th-block元素。

重要,这种语法是对命名空间th:*的一种增加,而不是替换。没有任何打算在将来会弃用命名空间语法。

6 迭代

6.1 迭代基本要素

标准的方言给我们提供了一个确切的属性,th:each
使用th:each:

 1<!DOCTYPE html>
 2<html xmlns:th="http://www.thymeleaf.org">
 3  <head>
 4    <title>Good Thymes Virtual Grocery</title>
 5    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 6    <link rel="stylesheet" type="text/css" media="all" 
 7          href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
 8  </head>
 9  <body>
10    <h1>Product list</h1>
11    <table>
12      <tr>
13        <th>NAME</th>
14        <th>PRICE</th>
15        <th>IN STOCK</th>
16      </tr>
17      <tr th:each="prod : ${prods}">
18        <td th:text="${prod.name}">Onions</td>
19        <td th:text="${prod.price}">2.41</td>
20        <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
21      </tr>
22    </table>
23    <p>
24      <a href="../home.html" th:href="@{/}">Return to home</a>
25    </p>
26  </body>
27</html>

prod : ${prods}属性值的意思是,对于${prods}计算结果中的每一个元素,重复模板的这个片段,使用当前元素在一个变量里叫做prod。让我们给看到的每个事物起一个名字:
把${prods}叫做被迭代表达式或被迭代变量
把prod叫做迭代变量

注意,prod迭代变量的范围是<tr>元素里,这意味着它对内部标签<td>是可用的。

可迭代的值

java.util.List并不是唯一的值,有一个完整的可迭代对象集合:

任何对象实现java.util.Iterable
任何对象实现java.util.Enumeration
任何对象实现java.util.Iterator
任何对象实现java.util.Map。当迭代map时,迭代变量是java.util.Map.Entry类型
任何数组
任何其它的对象将被认为它好像是只有一个元素的列表,而这个元素就是它自己

6.2 保持迭代状态

当时用th:each,thymeleaf提供一个有用的机制来保持你的迭代状态的跟踪,status变量。

status变量被定义在th:each属性里,且包含下面的数据:
当前的迭代索引,从0开始。这是index属性。
当前的迭代索引,从1开始。这是count属性。
被迭代变量里的元素总数。这是size属性。
每一次迭代的迭代变量。这是current属性。
当前迭代是奇数或偶数。它们是even/odd布尔属性。
当前迭代是否第一个。这是first布尔属性。
当前迭代是否最后一个。这是last布尔属性。

让我们看看如何使用它:

 1<table>
 2  <tr>
 3    <th>NAME</th>
 4    <th>PRICE</th>
 5    <th>IN STOCK</th>
 6  </tr>
 7  <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? ‘odd‘">
 8    <td th:text="${prod.name}">Onions</td>
 9    <td th:text="${prod.price}">2.41</td>
10    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
11  </tr>
12</table>

status变量(上例中是iterStat)定义在th:each属性里,通过在迭代变量自己后面写上它的名字,且使用逗号分隔。就像迭代变量一样,status变量的范围也被限定在持有th:each属性的那个标签定义的代码片段里。

让我们看一看模板的处理结果:

 1<!DOCTYPE html>
 2<html>
 3  <head>
 4    <title>Good Thymes Virtual Grocery</title>
 5    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
 6    <link rel="stylesheet" type="text/css" media="all" href="/gtvg/css/gtvg.css" />
 7  </head>
 8  <body>
 9    <h1>Product list</h1>
10    <table>
11      <tr>
12        <th>NAME</th>
13        <th>PRICE</th>
14        <th>IN STOCK</th>
15      </tr>
16      <tr class="odd">
17        <td>Fresh Sweet Basil</td>
18        <td>4.99</td>
19        <td>yes</td>
20      </tr>
21      <tr>
22        <td>Italian Tomato</td>
23        <td>1.25</td>
24        <td>no</td>
25      </tr>
26      <tr class="odd">
27        <td>Yellow Bell Pepper</td>
28        <td>2.50</td>
29        <td>yes</td>
30      </tr>
31      <tr>
32        <td>Old Cheddar</td>
33        <td>18.75</td>
34        <td>yes</td>
35      </tr>
36    </table>
37    <p>
38      <a href="/gtvg/" shape="rect">Return to home</a>
39    </p>
40  </body>
41</html>

注意,我们的status变量工作的很好,只在奇数行上建立odd CSS类。

如果你没有显式地设置一个status变量,thymeleaf将总是为你创建一个,名字就是在迭代变量名字上加个后缀Stat。

 1<table>
 2  <tr>
 3    <th>NAME</th>
 4    <th>PRICE</th>
 5    <th>IN STOCK</th>
 6  </tr>
 7  <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? ‘odd‘">
 8    <td th:text="${prod.name}">Onions</td>
 9    <td th:text="${prod.price}">2.41</td>
10    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
11  </tr>
12</table>

7 条件计算

7.1 简单的条件if和unless

使用th:if属性:

 1<table>
 2  <tr>
 3    <th>NAME</th>
 4    <th>PRICE</th>
 5    <th>IN STOCK</th>
 6    <th>COMMENTS</th>
 7  </tr>
 8  <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? ‘odd‘">
 9    <td th:text="${prod.name}">Onions</td>
10    <td th:text="${prod.price}">2.41</td>
11    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
12    <td>
13      <span th:text="${#lists.size(prod.comments)}">2</span> comment/s
14      <a href="comments.html" 
15         th:href="@{/product/comments(prodId=${prod.id})}" 
16         th:if="${not #lists.isEmpty(prod.comments)}">view</a>
17    </td>
18  </tr>
19</table>

让我们聚焦关键行:

1<a href="comments.html"
2   th:href="@{/product/comments(prodId=${prod.id})}" 
3   th:if="${not #lists.isEmpty(prod.comments)}">view</a>
4

让我们看看结果:

 1<table>
 2  <tr>
 3    <th>NAME</th>
 4    <th>PRICE</th>
 5    <th>IN STOCK</th>
 6    <th>COMMENTS</th>
 7  </tr>
 8  <tr>
 9    <td>Fresh Sweet Basil</td>
10    <td>4.99</td>
11    <td>yes</td>
12    <td>
13      <span>0</span> comment/s
14    </td>
15  </tr>
16  <tr class="odd">
17    <td>Italian Tomato</td>
18    <td>1.25</td>
19    <td>no</td>
20    <td>
21      <span>2</span> comment/s
22      <a href="/gtvg/product/comments?prodId=2">view</a>
23    </td>
24  </tr>
25  <tr>
26    <td>Yellow Bell Pepper</td>
27    <td>2.50</td>
28    <td>yes</td>
29    <td>
30      <span>0</span> comment/s
31    </td>
32  </tr>
33  <tr class="odd">
34    <td>Old Cheddar</td>
35    <td>18.75</td>
36    <td>yes</td>
37    <td>
38      <span>1</span> comment/s
39      <a href="/gtvg/product/comments?prodId=4">view</a>
40    </td>
41  </tr>
42</table>

注意,th:if属性不仅能计算布尔条件。它的能力会有一点超出,它将按照下面的这些规则,把特定的表达式计算作为true:
如果value不是null:
如果value是一个布尔值,且是true
如果value是一个数字值,且不为0
如果value是一个字符,且不为0
如果value是一个字符串,且不是false,off或no
如果value不是一个布尔值/一个数字值/一个字符/一个字符串
如果value是null,将计算为false

同样,th:if有一个相反的属性,th:unless,它能够用在上一个示例中而不用在OGNL表达式中加not:

1<a href="comments.html"
2   th:href="@{/comments(prodId=${prod.id})}" 
3   th:unless="${#lists.isEmpty(prod.comments)}">view</a>
4

7.2 Switch语句

还有有一种方式可以有条件地显示内容,和java中的switch结构相等。th:switch/th:case属性集合:

1<div th:switch="${user.role}">
2  <p th:case="‘admin‘">User is an administrator</p>
3  <p th:case="#{roles.manager}">User is a manager</p>
4</div>

注意,一旦有一个th:case属性被计算作为true,在同一个switch上下文的每个其它的th:case属性被计算作为false。

默认的选项被指定像th:case="*":

1<div th:switch="${user.role}">
2  <p th:case="‘admin‘">User is an administrator</p>
3  <p th:case="#{roles.manager}">User is a manager</p>
4  <p th:case="*">User is some other thing</p>
5</div>

(完)

Thymeleaf(第五/六/七章)设置属性值/迭代/条件计算

标签:log   相等   代码   for   lang   规则   选项   null   each   

原文地址:https://blog.51cto.com/15049788/2562555

版权声明:完美者 发表于 2020-12-16 12:23:13。
转载请注明:Thymeleaf(第五/六/七章)设置属性值/迭代/条件计算 | 完美导航

暂无评论

暂无评论...