领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

可能是最全的Thymeleaf参考手册(六):迭代

nixiaole 2024-11-26 07:08:53 知识剖析 21 ℃

在前端页面中,总是出现需要遍历集合中的元素以展示所有信息的场景。Thymeleaf标准方言为我们提供了一个有用的属性:th:each


用法


假设后台控制器添加了一个商品列表的属性 prods。然后,我们使用 th:each 在模板中使用来遍历产品列表:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

  <head>
    <title>Good Thymes Virtual Grocery</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all" 
          href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
  </head>

  <body>

    <h1>Product list</h1>
  
    <table>
      <tr>
        <th>NAME</th>
        <th>PRICE</th>
        <th>IN STOCK</th>
      </tr>
      <tr th:each="prod : ${prods}">
        <td th:text="${prod.name}">Onions</td>
        <td th:text="${prod.price}">2.41</td>
        <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
      </tr>
    </table>
  
    <p>
      <a href="../home.html" th:href="@{/}">Return to home</a>
    </p>

  </body>

</html>

prod : ${prods} 属性的含义为:循环 ${prods} 属性的每一个元素。${prods} 为被迭代变量,prod 为迭代变量,即当前循环的元素。


需要注意的是,prod 为迭代变量的作用域为 <tr> 元素,可用于其内部标记 <td>


可迭代对象


java.util.List 类并不是Thymeleaf中唯一的可被用于迭代的对象。还有一些其它的可被迭代的集合对象:

  • 任何实现于 java.util.Iterable 的对象
  • 任何实现于 java.util.Enumeration 的对象
  • 任何实现于 java.util.Iterator 的对象,其值将由迭代器返回,而无需在内存中缓存
  • 任何实现于 java.util.Map 的对象,当迭代 Map 对象时,迭代对象则是 java.util.Map.Entry
  • 任何数组
  • 任何包含其对象本身的单值列表


迭代状态


在使用 th:each 时,Thymeleaf提供了一种用于跟踪迭代状态的有用机制:状态变量。

状态变量在 th:each 属性中定义,并且包含以下数据:

  • index 属性,当前的迭代索引,从0开始。
  • count 属性,从1开始的当前迭代索引。
  • size 属性,迭代变量中元素的总数。
  • current 属性,每次迭代的变量。
  • even/odd 布尔属性,当前迭代是偶数还是奇数。
  • first 布尔属性,当前迭代是否是第一个。
  • last 布尔属性,当前迭代是否为最后一个。


示例:

<table>
  <tr>
    <th>NAME</th>
    <th>PRICE</th>
    <th>IN STOCK</th>
  </tr>
  <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
  </tr>
</table>

状态变量(本例中为 iterStat)通过在 th:each 属性中迭代变量后写入名称,并以逗号分隔。同样的,其作用域与定义 th:each 属性的代码片段一致。


如果未明确设置状态变量,则Thymeleaf将始终通过在迭代变量名后添加 Stat 后缀来创建:

<table>
  <tr>
    <th>NAME</th>
    <th>PRICE</th>
    <th>IN STOCK</th>
  </tr>
  <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
  </tr>
</table>


惰性加载


有时候我们想优化数据的检索方式,比如在真正用到这些数据时才检索。


实际上,这可以应用于任何数据,但是考虑到内存中集合可能具有的大小,对于这种情况,检索要迭代的集合是最常见的情况。


为了支持这一特性,Thymeleaf提供了一种延迟加载上下文变量的机制。实现 ILazyContextVariable 接口的上下文变量(很可能是通过扩展其 LazyContextVariable 默认实现)将在执行时解析。例如:

model.addAttribute(
     "users",
     new LazyContextVariable<List<User>>() {
         @Override
         protected List<User> loadValue() {
             return databaseRepository.findAllUsers();
         }
     });


可以在不了解其惰性加载特性的情况下使用此变量,例如:

<ul>
  <li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>

但是同时, 如果在以下代码中 condition 计算为 false,则将永远不会初始化(loadValue() 方法永远不会调用):

<ul th:if="${condition}">
  <li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>
最近发表
标签列表