欢迎您的访问
专注于分享最有价值的互联网技术干货

六、Iteration

几个T的资料等你来白嫖
双倍快乐
一定要收藏这个宝藏网站防止丢失,求助资源~!!!

六、Iteration

到目前为止,我们已经创建了一个主页,一个用户 Profile 页面以及一个允许用户订阅我们的新闻通讯的页面……但是我们的产品呢?为此,我们将需要一种方法来遍历集合中的项目以构建我们的产品页面。

6.1 迭代基础

要在我们的/WEB-INF/templates/product/list.html页面上显示产品,我们将使用一个表格。我们的每种产品都将显示在一行中(一个<tr>元素),因此对于我们的模板,我们需要创建一个* template row (模板行),该行将举例说明我们希望每种产品的展示方式,然后指示 Thymeleaf 对每个产品重复一次。

标准方言为我们提供了一个确切的属性:th:each

Using th:each

对于我们的产品列表页面,我们将需要一个控制器方法,该方法从服务层检索产品列表并将其添加到模板上下文中:

public void process(
        final HttpServletRequest request, final HttpServletResponse response,
        final ServletContext servletContext, final ITemplateEngine templateEngine)
        throws Exception {

    ProductService productService = new ProductService();
    List<Product> allProducts = productService.findAll(); 

    WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());
    ctx.setVariable("prods", allProducts);

    templateEngine.process("product/list", ctx, response.getWriter());

}

然后,我们将在模板中使用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}的结果中的每个元素,使用名为 prod 的变量中的当前元素,重复此模板片段。”让我们给每一个看到的事物命名:

  • 我们将${prods}称为迭代表达式迭代变量
  • 我们将prod称为迭代变量或简称为* iter 变量*。

请注意,prod iter 变量的作用域为<tr>元素,这意味着它可用于<td>之类的内部标记。

Iterable values

java.util.List类不是 Thymeleaf 中唯一可用于迭代的值。有相当完整的一组对象,它们被th:each属性视为“可迭代”:

  • 任何实现java.util.Iterable的对象
  • 任何实现java.util.Enumeration的对象。
  • 实现java.util.Iterator的任何对象,其值将由迭代器返回,而无需在内存中缓存所有值。
  • 任何实现java.util.Map的对象。迭代 Map 时,迭代变量将属于java.util.Map.Entry类。
  • Any array.
  • 任何其他对象都将被视为包含该对象本身的单值列表。

6.2 保持迭代状态

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

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

  • 当前的迭代索引,从 0 开始。这是index属性。
  • 从 1 开始的当前* iteration index *。这是count属性。
  • 迭代变量中元素的总数。这是size属性。
  • 每次迭代的* iter 变量*。这是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属性中定义的,方法是在 iter 变量本身之后写入名称,并用逗号分隔。就像 iter 变量一样,status 变量的范围也由持有th:each属性的标签所定义的代码片段组成。

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

<!DOCTYPE html>

<html>

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

  <body>

    <h1>Product list</h1>

    <table>
      <tr>
        <th>NAME</th>
        <th>PRICE</th>
        <th>IN STOCK</th>
      </tr>
      <tr class="odd">
        <td>Fresh Sweet Basil</td>
        <td>4.99</td>
        <td>yes</td>
      </tr>
      <tr>
        <td>Italian Tomato</td>
        <td>1.25</td>
        <td>no</td>
      </tr>
      <tr class="odd">
        <td>Yellow Bell Pepper</td>
        <td>2.50</td>
        <td>yes</td>
      </tr>
      <tr>
        <td>Old Cheddar</td>
        <td>18.75</td>
        <td>yes</td>
      </tr>
    </table>

    <p>
      <a href="/gtvg/" shape="rect">Return to home</a>
    </p>

  </body>

</html>

请注意,我们的迭代状态变量运行得很好,仅对奇数行构建了odd CSS 类。

如果您未明确设置状态变量,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>

6.3 通过延迟检索数据进行优化

有时我们可能想优化数据集合的检索(例如从数据库中),以便仅在 true 要使用它们的情况下才检索这些集合。

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

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

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

在不了解其* lazyness *的情况下,可以在以下代码中使用此变量:

<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>
赞(0) 打赏
版权归原创作者所有,任何形式转载请联系我们:大白菜博客 » 六、Iteration

评论 抢沙发

0 + 7 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏