为分支语句,与 javascript 中的 if 类似。

    如果 variable 定义了并且为 true (译者注:这里并非布尔值,和 javascript 的处理是一样的) 则会显示 "It is true",否则什么也不显示。

    1. {% if hungry %}
    2. I am hungry
    3. {% elif tired %}
    4. I am tired
    5. {% else %}
    6. I am good!
    7. {% endif %}

    在(inline expression)中也可以使用 if。

    for

    for 可以遍历数组 (arrays) 和对象 (dictionaries)。

    1. var items = [{ title: "foo", id: 1 }, { title: "bar", id: 2}];
    1. <h1>Posts</h1>
    2. <ul>
    3. {% for item in items %}
    4. <li>{{ item.title }}</li>
    5. {% else %}
    6. <li>This would display if the 'item' collection were empty</li>
    7. {% endfor %}
    8. </ul>

    上面的示例通过使用items数组中的每一项的title属性显示了所有文章的标题。如果items数组是空数组的话则会渲染else语句中的内容。

    你还可以遍历对象:

    1. var food = {
    2. 'ketchup': '5 tbsp',
    3. 'mustard': '1 tbsp',
    4. 'pickle': '0 tbsp'
    5. };
    1. {% for ingredient, amount in food %}
    2. Use {{ amount }} of {{ ingredient }}
    3. {% endfor %}

    过滤器可将对象排序 (new in 0.1.8)

    除此之外,Nunjucks 会将数组解开,数组内的值对应到变量 (new in 0.1.8)

    1. var points = [[0, 1, 2], [5, 6, 7], [12, 13, 14]];
    1. {% for x, y, z in points %}
    2. Point: {{ x }}, {{ y }}, {{ z }}
    3. {% endfor %}

    在循环中可获取一些特殊的变量

    • loop.index0: 当前循环数 (0 indexed)
    • loop.revindex: 当前循环数,从后往前 (1 indexed)
    • loop.revindex0: 当前循环数,从后往前 (0 based)
    • loop.first: 是否第一个
    • loop.last: 是否最后一个
    • loop.length: 总数

    asyncEach

    asyncEachfor 的异步版本,只有当使用的时候才使用,否则请不要使用。异步过滤器和扩展也需要他。如果你在循环中使用了异步过滤器的话,Nunjucks就会在内部自动将循环转换成 asyncEach

    asyncEachfor 的使用方式一致,但他支持循环的异步控制。将两者区分的原因是性能,大部分人使用同步模板,将 for 转换成原生的 for 语句会快很多。

    编译时 nunjuck 不用关心模板是如何加载的,所以无法决定 include 是同步或异步。这也是为什么Nunjucks无法自动将普通的循环语句转换成异步循环语句的原因,所以如果你要使用异步模板加载器的话,就需要使用 asyncEach

    1. // If you are using a custom loader that is async, you need asyncEach
    2. var env = new nunjucks.Environment(AsyncLoaderFromDatabase, opts);
    1. <h1>Posts</h1>
    2. <ul>
    3. {% include "item-template.html" %}
    4. {% endeach %}
    5. </ul>

    asyncAll

    asyncAllasyncEach 类似,但 asyncAll 会并行的执行,并且每项的顺序仍然会保留。除非使用异步的过滤器、扩展或加载器,否则不要使用。

    如果你写了一个 lookup 的过滤器用来从数据库获取一些文本,使用 asyncAll 可以并行渲染。

    如果 lookup 是一个异步的过滤器,那么可能会比较慢(如从磁盘获取些数据)。asyncAll 会减少执行的时间,他会并行执行所有的异步操作,当所有的操作完成后才会继续渲染页面。

    宏 (macro) 可以定义可复用的内容,类似与编程语言中的函数,看下面的示例:

    1. {% macro field(name, value='', type='text') %}
    2. <div class="field">
    3. <input type="{{ type }}" name="{{ name }}"
    4. value="{{ value | escape }}" />
    5. </div>
    6. {% endmacro %}
    1. {{ field('user') }}
    2. {{ field('pass', type='password') }}

    支持,通过链接查看具体使用方式。

    还可以从其他模板 import 宏,可以使宏在整个项目中复用。

    重要:如果你使用异步 API,请注意你 不能 在宏中做任何异步的操作,因为宏只是像函数一样被简单地调用。将来我们可能会提供一种异步的宏调用方式,但现在这么使用是不被支持的。

    set

    set 可以设置和修改变量。

    1. {{ username }}
    2. {% set username = "joe" %}
    3. {{ username }}

    如果 username 初始化的时候为 "james', 最终将显示 "james joe"。

    可以设置新的变量,并一起赋值。

    1. {% set x, y, z = 5 %}

    如果在顶级作用域使用 set,将会改变全局的上下文中的值。如果只在某个作用域 (像是include或是macro) 中使用,则只会影响该作用域。

    同样地,你也可以使用区块赋值将一个区块的内容储存在一个变量中。

    它的语法和标准的set语法相似,只不过你不需要用=。区块中从头到{% endset %}之间的内容都会被捕获,并作为值来使用。

    在某些情境下,你可以用这种语法来替代宏:

    1. {% set standardModal %}
    2. {% include 'standardModalData.html' %}
    3. {% endset %}
    4. <div class="js-modal" data-modal="{{standardModal | e}}">

    extends

    extends 用来指定模板继承,被指定的模板为父级模板,查看。

    1. {% extends "base.html" %}

    你可以将继承的模板设为一个变量,这样就可以动态指定继承的模板。这个变量既可以是个指向模板文件的字符串,也可以是个模板编译后所生成的对象(需要添加上下文环境)。因此你可以通过设置上下文变量,从而在渲染时动态地改变所要继承的模板。

    1. {% extends parentTemplate %}

    extends也可以接受任意表达式,只要它最终返回一个字符串或是模板所编译成的对象:

    1. {% extends name + ".html" %}`.

    block

    区块(block) 定义了模板片段并标识一个名字,在模板继承中使用。父级模板可指定一个区块,子模板覆盖这个区块,查看。

    1. {% block css %}
    2. <link rel="stylesheet" href="app.css" />
    3. {% endblock %}

    可以在循环中定义区块

    子模板可以覆盖 item 区块并改变里面的内容。

    1. {% extends "item.html" %}
    2. {% block item %}
    3. The name of the item is: {{ item.name }}

    include 可引入其他的模板,可以在多模板之间共享一些小模板,如果某个模板已使用了继承那么 include 将会非常有用。

    1. {% include "item.html" %}

    可在循环中引入模板

    1. {% for item in items %}
    2. {% include "item.html" %}

    这一点可以帮助我们把模板切分成更小的部分,从而使得在浏览器上,当我们需要改变页面时,我们可以渲染这些小部分的模板,而非一整个的大的模板。

    include 可以接受任意表达式,只要它最终返回一个字符串或是模板所编译成的对象: {% include name + ".html" as obj %}.

    在某些情况下,我们可能希望在模板文件不存在时不要抛出异常。对于这类情况,我们可以使用ignore missing来略过这些异常:

    1. {% include "missing.html" ignore missing %}

    被包含的模版自身可以扩展(extends)另一个模版(因此你可以让一系列相关联的模版继承同一种结构)。一个被包含的模版并不会改变包含它的模版的区块结构,它有一个分离的继承树和块级命名空间。换言之,在渲染时,include并不 不是 将被包含模版代码拉取到包含它的模版中的预处理器。相对的,它对被包含的模版触发了一次的分离渲染,然后再将渲染的结果引入。

    import

    import 可加载不同的模板,可使你操作模板输出的数据,模板将会输出宏 (macro) 和在顶级作用域进行的赋值 (使用 )。

    被 import 进来的模板没有当前模板的上下文,所以无法使用当前模板的变量,

    创建一个叫 forms.html 如下所示

    1. {% macro field(name, value='', type='text') %}
    2. <div class="field">
    3. <input type="{{ type }}" name="{{ name }}"
    4. value="{{ value | escape }}" />
    5. </div>
    6. {% endmacro %}
    7. {% macro label(text) %}
    8. <div>
    9. <label>{{ text }}</label>
    10. </div>
    11. {% endmacro %}

    我们可以 import 这个模板并将模板的输出绑定到变量 forms 上,然后就可以使用这个变量了:

    1. {% import "forms.html" as forms %}
    2. {{ forms.label('Username') }}
    3. {{ forms.field('user') }}
    4. {{ forms.label('Password') }}
    5. {{ forms.field('pass', type='password') }}

    也可以使用 from import 从模板中 import 指定的值到当前的命名空间:

    1. {% from "forms.html" import input, label as description %}
    2. {{ description('Username') }}
    3. {{ input('user') }}
    4. {{ description('Password') }}
    5. {{ input('pass', type='password') }}

    import 可以接受任意表达式,只要它最终返回一个字符串或是模板所编译成的对象: {% import name + ".html" as obj %}.

    raw

    如果你想输出一些 Nunjucks 特殊的标签 (如 {{),可以使用 {{),可以使用 {% raw %} 将所有的内容输出为纯文本。

    filter

    filter区块允许我们使用区块中的内容来调用过滤器。不同于使用|语法,它会将区块渲染出的内容传递给过滤器。

    1. {% filter title %}
    2. may the force be with you
    3. {% endfilter %}
    4. {% filter replace("force", "forth") %}
    5. may the force be with you
    6. {% endfilter %}

    切记:你不能在这些区块中进行任何异步操作。

    call区块允许你使用标签之间的内容来调用一个宏。这在你需要给宏传入大量内容时是十分有用的。在宏中,你可以通过caller()来获取这些内容。

    1. {% macro add(x, y) %}
    2. {{ caller() }}: {{ x + y }}
    3. {% endmacro%}
    4. {% call add(1, 2) -%}
    5. {%- endcall %}