如何在模板中精确控制列表循环的计数和迭代顺序?

在安企CMS中,内容列表是我们网站的核心组成部分,无论是文章列表、产品展示还是其他数据模块,都离不开在模板中循环遍历数据并进行展示。高效且精准地控制这些列表的循环行为,不仅能让内容呈现更灵活多样,也能显著提升用户体验和网站的整体表现。安企CMS的模板引擎借鉴了Django的语法,为我们提供了强大的列表循环控制能力。

基础循环与迭代概览

首先,让我们从最基本的循环标签 {% for %} 开始。在安企CMS的模板中,当我们希望展示一个内容集合(比如一系列文章或产品)时,通常会结合如 archiveListcategoryListpageList 这样的数据标签来获取数据,然后使用 for 循环标签来遍历这些数据。

一个典型的例子是获取并显示文章列表:

{% archiveList archives with type="list" limit="10" %}
    {% for item in archives %}
        <div class="article-item">
            <h3><a href="{{item.Link}}">{{item.Title}}</a></h3>
            <p>{{item.Description}}</p>
        </div>
    {% endfor %}
{% endarchiveList %}

在这里,archivesarchiveList 标签返回的文章集合,item 则是循环中每一篇文章的变量。理解这个基础结构,是后续精准控制的关键。

精准掌握循环计数与位置

在很多场景下,我们不仅仅是简单地遍历数据,还需要知道当前循环到了第几项,或者距离循环结束还有多少项。安企CMS为此提供了 forloop.Counterforloop.Revcounter 这两个非常有用的变量:

  • forloop.Counter: 这个变量会返回当前循环的次数,从 1 开始递增。它非常适合用来显示序号,或者判断是否是列表中的第一项、第二项。
  • forloop.Revcounter: 这个变量则返回当前项距离循环结束还剩余多少项,同样从 1 开始递减。当你需要为列表中的最后一项或倒数几项做特殊处理时,它就显得尤为方便。

假设我们想给文章列表加上序号,并且标识出倒数第二篇文章:

{% archiveList archives with type="list" limit="10" %}
    {% for item in archives %}
        <div class="article-item {% if forloop.Revcounter == 2 %}last-second-item{% endif %}">
            <span class="index">{{forloop.Counter}}.</span>
            <h3><a href="{{item.Link}}">{{item.Title}}</a></h3>
            <p>{{item.Description}}</p>
        </div>
    {% endfor %}
{% endarchiveList %}

这样的代码不仅清晰地展示了文章序号,还通过判断 forloop.Revcounter 的值,给倒数第二篇文章添加了特殊的CSS类,方便进行样式定制。

灵活调整迭代顺序:reversedsorted

有时,我们希望以特定的顺序来遍历已获取的数据。安企CMS的 for 循环标签支持 reversedsorted 关键字,来改变迭代的顺序:

  • reversed: 如果你想将数据按相反的顺序进行遍历,可以在 for 标签后加上 reversed。比如,原本按发布时间从新到旧的列表,加上 reversed 后就会从旧到新显示。
  • sorted: 这个关键字允许你对列表中的元素进行排序。它通常对包含可排序值(如数字、字符串)的列表更有效。需要注意的是,对于通过 archiveList 标签获取的内容数据,我们更多是通过 order 参数在数据获取阶段进行排序,sorted 更多适用于通用数据数组。

例如,如果我们有一个简单的数字列表 myNumbers = [5, 2, 8, 1],我们可以这样遍历:

{% set myNumbers = "[5,2,8,1]"|list %}
<div>
    <p>原始顺序:</p>
    {% for num in myNumbers %}
        <span>{{num}} </span>
    {% endfor %}
</div>
<div>
    <p>反转顺序:</p>
    {% for num in myNumbers reversed %}
        <span>{{num}} </span>
    {% endfor %}
</div>
<div>
    <p>排序后:</p>
    {% for num in myNumbers sorted %}
        <span>{{num}} </span>
    {% endfor %}
</div>

这将分别输出 5 2 8 11 8 2 51 2 5 8

循环中的条件化展示:if 标签的妙用

在循环中嵌套 if 逻辑判断标签,能够实现更细致的展示控制。这对于突出显示特定内容、或根据某些条件改变内容布局非常有用。

除了利用 forloop.Counterforloop.Revcounter 来判断首尾项之外,我们还可以根据业务需求对数据项的属性进行判断:

{% archiveList articles with type="list" limit="8" flag="c" %} {# 获取推荐文章 #}
    {% for article in articles %}
        {% if forloop.Counter == 1 %}
            <div class="featured-article">
                <h2><a href="{{article.Link}}">{{article.Title}}</a></h2>
                <p>这是特别推荐的第一篇文章,不容错过!</p>
            </div>
        {% elif article.Views > 1000 %}
            <div class="popular-article">
                <h4><a href="{{article.Link}}">{{article.Title}}</a></h4>
                <span>阅读量已破千!</span>
            </div>
        {% else %}
            <div class="normal-article">
                <h5><a href="{{article.Link}}">{{article.Title}}</a></h5>
            </div>
        {% endif %}
    {% endfor %}
{% endarchiveList %}

这段代码为第一篇文章设置了独特的样式,阅读量超过一千的文章也有单独的样式,其他文章则显示为普通样式,极大地丰富了内容的视觉层次。

优雅处理空列表:empty 标签

有时,通过 archiveList 或其他标签查询出的结果可能为空。如果不对这种情况进行处理,页面上可能会出现空白或者不友好的提示。{% empty %} 标签能帮助我们优雅地处理这种情况:

{% archiveList searchResults with type="page" q=urlParams.q limit="10" %}
    {% for item in searchResults %}
        <div class="search-result-item">
            <h4><a href="{{item.Link}}">{{item.Title}}</a></h4>
            <p>{{item.Description}}</p>
        </div>
    {% empty %}
        <div class="no-results">
            <p>抱歉,没有找到您搜索的 "{{urlParams.q}}" 相关内容。</p>
            <p>您可以尝试更换关键词或浏览其他分类。</p>
        </div>
    {% endfor %}
{% endarchiveList %}

searchResults 列表为空时,{% empty %} 块中的内容就会被渲染出来,为用户提供了清晰的反馈。

循环中的交替模式:cycle 标签

如果你需要为列表中的每一项应用重复的样式或文本模式,例如,让相邻的列表项背景色不同,cycle 标签是一个非常实用的工具:

{% archiveList products with type="list" limit="6" %}
    {% for product in products %}
        <div class="product-card {% cycle 'odd-bg' 'even-bg' %}">
            <img src="{{product.Thumb}}" alt="{{product.Title}}">
            <h5><a href="{{product.Link}}">{{product.Title}}</a></h5>
        </div>
    {% endfor %}
{% endarchiveList %}

在这里,{% cycle 'odd-bg' 'even-bg' %} 会在每次循环时交替输出 'odd-bg''even-bg' 这两个字符串,我们可以将其作为 CSS 类名,轻松实现斑马线效果的列表样式。

优化数据源:列表标签的参数

虽然上述方法能精确控制循环迭代的方式,但真正的“精确控制”往往从数据源开始。安企CMS的列表标签(如 `