nunjucks: 学习笔记

一个后端渲染的模板引擎
更新于: 2025-08-06 20:16:54

cheatsheet

用法示例
变量渲染
const data = {
  name: "aric",
  city: "sh",
  nested: {
    prop1: "value1",
  },
};
const tpl = "Hello {{ name }}, you are from {{ city }}. nested value is : {{ nested.prop1 }}";
const output = nunjucks.renderString(tpl, data);
console.log(output);
过滤器
const nunjucks = require('nunjucks');

const tmpl = `
<p>{{ "   some string   " | trim }}</p>
<p>{{ [1, 2, 3] | join(", ") }}</p>
<p>{{ "hello" | upper }}</p>
`;

const output = nunjucks.renderString(tmpl);
console.log(output);

=========== results ================
<p>some string</p>
<p>1, 2, 3</p>
<p>HELLO</p>
过滤器组合
{{ foo | title }}
{{ foo | join(",") }}
{{ foo | replace("foo", "bar") | capitalize }}
自定义 filter
var nunjucks = require('nunjucks');
var env = new nunjucks.Environment();

env.addFilter('shorten', function(str, count) {
    return str.slice(0, count || 5);
});

=========== usage ================

{# Show the first 5 characters #}
A message for you: {{ message|shorten }}

{# Show the first 20 characters #}
A message for you: {{ message|shorten(20) }}
if
{% if variable %}
  It is true
{% endif %}
if/else
{% if hungry %}
  I am hungry
{% elif tired %}
  I am tired
{% else %}
  I am good!
{% endif %}
for(array/object)
const nunjucks = require("nunjucks");

nunjucks.configure("src");

const tmpl = `
<ul>
{% for key, value in food %}
  <li>Use {{ value }} of {{ key }}</li>
{% endfor %}
</ul>
`;

const output = nunjucks.renderString(tmpl, {
  food: {
    ketchup: "5 tbsp",
    mustard: "1 tbsp",
    pickle: "0 tbsp",
  },
});
include
{% include "item.html" %}

模板继承

  • parent(一般网站,这个就是 layout)
  • child

parent.tpl

{% block header %}
This is the default content
{% endblock %}

<section class="left">
  {% block left %}{% endblock %}
</section>

<section class="right">
  {% block right %}
  This is more content
  {% endblock %}
</section>

child.tpl

{% extends "parent.html" %}

{% block left %}
This is the left side!
{% endblock %}

{% block right %}
This is the right side!
{% endblock %}

最终 render 的 html 结果为

This is the default content

<section class="left">
  This is the left side!
</section>

<section class="right">
  This is the right side!
</section>

如果父级的内容是需要的可以使用 super

{% block right %}
{{ super() }}
Right side!
{% endblock %}

Macro

  • 多个(一个 tpl中定义多个)
  • 单个(一个tpl 中定义单个)

多个的场景

{% macro field(name, value='', type='text') %}
<div class="field">
  <input type="{{ type }}" name="{{ name }}"
         value="{{ value | escape }}" />
</div>
{% endmacro %}

{% macro label(text) %}
<div>
  <label>{{ text }}</label>
</div>
{% endmacro %}

多个导入使用

{% import "forms.html" as forms %}

{{ forms.label('Username') }}
{{ forms.field('user') }}
{{ forms.label('Password') }}
{{ forms.field('pass', type='password') }}

或者
{% from "forms.html" import input, label as description %}

{{ description('Username') }}
{{ input('user') }}
{{ description('Password') }}
{{ input('pass', type='password') }}

单个的导入

{% from "./commons/macros/latest-courses.tpl" import latestCourses %}

# 使用
{{ latestCourses(model) }}