`macro`标签在AnQiCMS模板中如何定义和调用,实现可复用的代码块显示?

AnQiCMS 提供了灵活强大的模板系统,让网站内容的展示既高效又美观。在模板开发中,为了提升代码的复用性和维护性,我们常常会遇到需要将一段常用的代码片段封装起来,以便在不同地方调用。这时,macro 标签就成了实现这一目标的关键工具。它允许我们定义可复用的代码块,就像编程语言中的函数一样。

为什么需要 macro 标签?

想象一下,如果您的网站有多种内容类型,比如文章列表、产品展示,它们可能在布局上有一些共同的元素,例如一个标题、一段简介和一张图片。如果每次都要重复编写这些元素的 HTML 结构,不仅效率低下,而且一旦需要修改样式或结构,就需要逐一查找并更新所有出现的地方,这无疑会带来巨大的维护成本。

macro 标签的出现正是为了解决这类问题。它允许您将这些重复的 HTML 结构连同其逻辑(例如,如何展示一个文章标题、如何格式化日期)一起封装成一个独立的、可调用的代码块。这样,您只需定义一次,便可在模板的任何地方多次调用,极大地提升了模板代码的模块化、可读性和可维护性。

如何定义一个 macro 代码块?

在 AnQiCMS 的模板中,定义 macro 的语法非常直观,它类似于定义一个函数:

{% macro macro_name(parameter1, parameter2, ...) %}
    {# 这里是可复用的代码块,可以使用传入的参数 #}
{% endmacro %}

macro 标签以 {% macro ... %} 开始,以 {% endmacro %} 结束。您需要为这个 macro 指定一个唯一的名称(例如 articleItem),并在括号中列出它将接受的参数。这些参数就像函数的输入,macro 内部的代码只能访问这些参数传递进来的变量。

例如,我们来定义一个用于显示文章列表项的 macro

{# 定义一个名为 "articleItem" 的宏,接受一个名为 "article" 的参数 #}
{% macro articleItem(article) %}
    <li class="article-card">
        <a href="{{ article.Link }}" title="{{ article.Title }}">
            <div class="card-image">
                {% if article.Thumb %}<img src="{{ article.Thumb }}" alt="{{ article.Title }}"/>{% endif %}
            </div>
            <h3 class="card-title">{{ article.Title }}</h3>
            <p class="card-description">{{ article.Description|truncatechars:80 }}</p>
            <div class="card-meta">
                <time>{{ stampToDate(article.CreatedTime, "2006-01-02") }}</time>
                <span>阅读量: {{ article.Views }}</span>
            </div>
        </a>
    </li>
{% endmacro %}

在这个例子中,articleItem 宏接受一个 article 对象作为参数。在宏的内部,我们使用 article.Linkarticle.Title 等来访问传入文章对象的属性,并利用 truncatechars 过滤器截取描述,使用 stampToDate 格式化时间。

调用已定义的 macro 代码块

定义好 macro 后,调用它就非常简单了。在同一模板文件中,您可以通过以下方式调用:

{# 假设我们使用 archiveList 标签获取了一系列文章数据 #}
{% archiveList articles with type="list" limit="5" %}
    <ul class="article-list">
    {% for item in articles %}
        {# 调用前面定义的 articleItem 宏,并传入当前循环的文章对象 #}
        {{ articleItem(item) }}
    {% endfor %}
    </ul>
{% empty %}
    <p>暂时没有文章内容。</p>
{% endarchiveList %}

在这里,我们在一个 for 循环中调用了 articleItem 宏,每次迭代都将当前的 item(即一篇文章对象)作为参数传递给宏。宏会按照其定义,生成对应的 HTML 结构。

跨文件复用 macroimport 的力量

对于大型项目,将所有 macro 都定义在一个文件里很快就会变得难以管理。AnQiCMS 允许您将 macro 定义在单独的文件中,并通过 import 标签将其引入到需要使用的模板里,实现真正的跨文件复用。

  1. 创建宏文件: 通常,我们会创建一个专门的目录(例如 _macrospartials/macros)来存放所有的宏文件。假设我们创建一个名为 _macros/article_card.html 的文件,并在其中定义上述 articleItem 宏:

    {# 文件路径: templates/your_theme/_macros/article_card.html #}
    {% macro articleItem(article) %}
        <li class="article-card">
            <a href="{{ article.Link }}" title="{{ article.Title }}">
                <div class="card-image">
                    {% if article.Thumb %}<img src="{{ article.Thumb }}" alt="{{ article.Title }}"/>{% endif %}
                </div>
                <h3 class="card-title">{{ article.Title }}</h3>
                <p class="card-description">{{ article.Description|truncatechars:80 }}</p>
                <div class="card-meta">
                    <time>{{ stampToDate(article.CreatedTime, "2006-01-02") }}</time>
                    <span>阅读量: {{ article.Views }}</span>
                </div>
            </a>
        </li>
    {% endmacro %}
    
    
    {# 如果有其他宏,也可以一同在此文件中定义 #}
    {% macro productCard(product) %}
        <li class="product-card">
            {# ... 产品卡片结构 ... #}
        </li>
    {% endmacro %}
    
  2. 在其他模板中导入并使用: 在 index.html 或其他任何需要使用这些宏的模板文件中,您可以使用 import 标签引入它们:

    {# 文件路径: templates/your_theme/index.html #}
    {% import "_macros/article_card.html" articleItem, productCard as myProductCardMacro %}
    
    
    <h1>最新文章</h1>
    {% archiveList articles with type="list" limit="5" %}
        <ul class="article-list">
        {% for item in articles %}
            {{ articleItem(item) }} {# 调用导入的 articleItem 宏 #}
        {% endfor %}
        </ul>
    {% endarchiveList %}
    
    
    <h1>推荐产品</h1>
    {% archiveList products with moduleId="2" type="list" limit="3" %}
        <ul class="product-list">
        {% for item in products %}
            {{ myProductCardMacro(item) }} {# 调用导入并设置别名的 productCard 宏 #}
        {% endfor %}
        </ul>
    {% endarchiveList %}
    

    通过 import,我们可以一次性导入一个或多个宏。使用逗号 , 分隔多个宏