在AnQiCMS进行模板开发时,我们经常会遇到需要处理一些复杂数据,或者重复使用某个计算结果的情况。为了让模板代码更简洁、易读、易于维护,AnQiCMS提供了一套强大的临时变量定义和使用机制,主要通过with和set这两个标签来实现。合理运用它们,可以大大提升我们内容显示的效率和灵活性。
简化内容显示:为什么需要临时变量?
想象一下,如果我们在模板中要多次显示同一个数据的某个属性,比如一篇文章的缩略图URL,或者一个分类的描述。每次都通过冗长的标签去获取,不仅代码看起来繁琐,而且一旦数据来源或处理逻辑发生变化,修改起来也会非常麻烦。此外,有些表达式本身就比较复杂,比如需要对时间戳进行格式化,或者从一个图片列表中提取第一张图片作为封面。这时候,如果能将这些中间结果存储在一个临时的“短名字”里,再在模板中引用这个短名字,无疑会让整个模板逻辑清晰许多。
AnQiCMS的模板引擎类似Django,它允许我们通过{{变量名}}来输出数据,并通过{% 标签 %}来控制逻辑。在这样的基础上,with和set标签就像是我们模板里的“小助手”,帮助我们暂存和管理这些中间数据。
使用 {% with %} 标签:局部作用域的优雅传递
with标签主要用于在一个特定的代码块内定义一个或多个临时变量。它的核心特点是“局部作用域”,也就是说,通过with定义的变量,只在{% with %}和{% endwith %}这对标签之间有效。一旦离开了这个代码块,这些变量就会失效。
基本语法:
{% with 变量名1=值1 变量名2=值2 %}
<!-- 在这里使用 {{变量名1}} 和 {{变量名2}} -->
{% endwith %}
with标签最常见的用途之一是给include(引入子模板)的模板传递变量。当我们引入一个公共的页头或页脚时,可能需要传递一些特定的信息,例如当前页面的标题或关键词。
示例:给引入的页头传递变量
假设我们有一个partial/header.html子模板,需要显示页面标题和关键词。
在主模板中,我们可以这样使用with来传递:
{% include "partial/header.html" with title="我的文章详情" keywords="AnQiCMS, 模板变量" %}
而在partial/header.html中,就可以直接使用这些变量了:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
<meta name="keywords" content="{{keywords}}">
<!-- 其他头部内容 -->
</head>
<body>
这种方式保证了子模板的独立性,也使得主模板的逻辑更加清晰。同时,如果只需要传递特定的变量,而不想让子模板访问主模板的所有变量,还可以在with后面加上only关键字来限制。
with标签的另一个优势是简化复杂表达式的临时存储。比如我们从archiveDetail获取了一个图片的URL,需要将其作为背景图,并可能在多个地方使用。
{% with articleLogo=archiveDetail with name='Logo' %}
<div class="article-header" style="background-image: url('{{articleLogo}}');">
<!-- ... -->
</div>
<img src="{{articleLogo}}" alt="文章Logo" class="article-logo">
{% endwith %}
在这里,articleLogo这个临时变量只在with块内生效,有效避免了重复的代码或过长的表达式。
使用 {% set %} 标签:更灵活的变量定义
相比with标签的局部作用域,set标签提供了一种更灵活的方式来定义变量。通过set定义的变量,其作用域从定义点开始,直到当前模板文件结束,或者直到遇到另一个同名变量的set重新赋值为止。这意味着set定义的变量可以在模板文件的更广范围内使用。
基本语法:
{% set 变量名 = 值 %}
set标签特别适合用于存储一些需要在模板不同区域反复使用的,或者经过复杂计算、筛选器处理后的结果。
示例:存储格式化后的时间
假设我们要显示文章的创建时间,并且需要将其格式化为“年-月-日”的形式。如果文章列表的每个条目都需要显示,那么反复调用{{stampToDate(item.CreatedTime, "2006-01-02")}}会比较繁琐。
{% archiveList archives with type="list" limit="5" %}
{% for item in archives %}
{% set formattedDate = stampToDate(item.CreatedTime, "2006-01-02") %}
<div class="article-item">
<h3><a href="{{item.Link}}">{{item.Title}}</a></h3>
<p>发布日期: {{formattedDate}}</p>
<!-- 其他地方也可以使用 formattedDate -->
</div>
{% endfor %}
{% endarchiveList %}
在这里,formattedDate变量在每次循环中都会被重新赋值,并且可以在当前循环的后续部分使用,直到下一次循环迭代开始。
示例:提取图片并复用 在分类详情页面,如果上传了多张Banner图,我们可能只希望提取第一张作为页面的大图背景。
{% categoryDetail bannerImages with name="Images" %}
{% if bannerImages %}
{% set pageBanner = bannerImages[0] %} {# 提取第一张图并赋值给 pageBanner #}
{% endif %}
<div class="page-banner" style="background: url('{{pageBanner}}') no-repeat center center / cover;">
<!-- Banner 内容 -->
</div>
<div class="page-intro">
<!-- 在这里,pageBanner 仍然有效 -->
<img src="{{pageBanner}}" alt="分类封面" class="intro-thumb">
<!-- ... -->
</div>
这里pageBanner变量在set定义后,可以在后续的div元素中继续使用,无需再次从bannerImages[0]中提取,大大提高了代码的简洁性和效率。
with与set的选择:何时用哪个?
选择with还是set,主要取决于你对变量作用域的需求:
使用
{% with %}:- 当你需要在局部代码块内(例如一个特定的HTML组件或
include一个子模板时)定义临时变量,并且这些变量不需要在代码块之外使用时,with是理想的选择。 - 它的局部作用域有助于避免变量名冲突,保持代码模块化。
- 当你需要在局部代码块内(例如一个特定的HTML组件或
使用
{% set %}:- 当你定义的变量需要在模板文件的更广范围内(从定义点到文件末尾)被多次引用,或者需要存储一个经过计算、筛选器处理后的结果供后续使用时,
set更为合适。 - 它提供了更大的灵活性,但也要注意变量名冲突的可能性,尤其是在大型模板文件中。
- 当你定义的变量需要在模板文件的更广范围内(从定义点到文件末尾)被多次引用,或者需要存储一个经过计算、筛选器处理后的结果供后续使用时,
通常,我们会结合使用这两种标签,以达到**的模板组织和内容显示效果。通过set定义一些全局性的页面数据,再通过with在局部组件中定义更具体的辅助变量,可以实现层次分明、易于管理的模板结构。
总结
AnQiCMS的with和set标签是模板开发中不可或缺的工具。它们能够帮助我们有效地管理模板中的数据,将复杂的数据处理逻辑封装成简洁的变量,从而大大提升模板代码的可读性、可维护性和开发效率。掌握它们的用法,将使您在AnQiCMS的内容运营中更加得心应手,轻松构建出高质量、灵活多变的内容展示页面。
常见问题 (FAQ)
{% set %}定义的变量能否在通过{% include %}引入的子模板中使用? 通常情况下,{% set %}定义的变量默认只在当前模板文件中有效,不会自动传递给include引入的子模板。如果需要在子模板中使用,您需要通过{% include "partial/header.html" with myVariable=someValue %}的方式显式地将变量作为参数传递进去。{% with %}和{% set %}定义的变量在循环(for标签)中表现有何不同?{% with %}定义的变量,其作用域仅限于当前的with块。如果在循环内部使用with定义变量,那么这个变量每次循环迭代都会重新定义,并在该迭代的with块结束后失效。{% set %}定义的变量,其作用域从定义点开始。如果在循环外部使用set定义变量,那么该变量在整个循环过程中都保持其值,除非在循环内部再次使用set对其进行重新赋值。如果在循环内部使用set定义变量,则该变量的作用域也仅限于当前循环迭代,但可以在该迭代的任意位置使用。是否可以在临时变量中存储复杂的数据结构,比如列表或对象? 是的,AnQiCMS 模板引擎允许您在
{% set %}或{% with %}中存储复杂的数据结构,例如通过archiveList获取的文档列表,或者tagDetail获取的标签对象。您可以将这些复杂对象赋值给临时变量,然后像往常一样使用点语法访问其属性或进行循环遍历。例如,{% set myArchives = archives %},之后您就可以像处理archives一样处理myArchives了。