Nunjucks 的四个杀手级特性

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

Nunjucks 自称“一种功能丰富且强大的 JavaScript 模板语言”,这听起来很正确。它不像 Mustache 或稍微健壮一些(但仍然非常轻量级)的 Handlebars 那样刻意追求超轻量级。它是一种完整的语言,包含了您在编写模板时可能需要的所有功能。

可以在浏览器中运行它,但可能不应该这样做。这旨在在 Node.js 中运行,并用于在服务器端编译模板。

换句话说:它是一个真正花哨的 HTML 预处理器。让我们看看我认为 Nunjucks 特别酷的一些特性。

友情提示:这非常主观,并且仅基于轻微的经验!我在这里只使用了 Nunjucks 能力的 10% 左右。

Nunjucks 是 Node 的东西,因此您可以使用 npm 安装它,并通过命令行、构建工具以及整个世界与之交互。

这是一个截图,显示我运行了一个 Node 脚本,该脚本呈现了一个 Nunjucks 模板

我运行了我的 Node 脚本,它将 nunjucks.render() 的结果记录到控制台

1. 它只是 HTML

请注意,我们传递给 nunjucks.render() 的文件实际上只是 HTML,其中包含 {{ handlebars }} 样式的模板语法。我将其命名为 `index.njk`,但这并不是必需的,我只是喜欢明确意图。

我敢打赌,有很多前端开发人员更喜欢在 HTML 中工作,即使 HTML 最终会被处理。我有时喜欢 Pug,但它是一种独立的空格依赖语言。更喜欢 Nunjucks 有点像更喜欢 ERB 而不是 HAML。

这是一个完全合法的模板

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>{{ page_title }}</title>
</head>

<body>

  {% for feature in features %}
    <div class="module">
      <h3>{{ feature.name }}</h3>
      <p>{{ feature.description }}</p>
    </div>
  {% endfor %}

</body>

</html>

什么是 features?数据!您将其传递给 render 函数。

nunjucks.render(
  'index.njk', {
    page_title: "Cool Product",
    features: [
      {
        name: "Speed",
        description: "It's fast."
      },
      {
        name: "Reliability",
        description: "You can count on it."
      },
      {
        name: "Security",
        description: "You don't have to worry about it."
      }
    ]
  }
);

您可以想象数据来自数据库或 API,我确定。您也可以根据需要在视图中直接定义数据。

<div>
  {% set foo = "bar" %}
  {{ foo }}
</div>

2. 包含

有时我使用一种语言仅仅是为了包含。例如,CodeKit 有一种几乎只用于包含的语言,因为他们知道包含多么有用。

以下是 Nunjucks 中包含的简单示例 包含

<body>

  {% include "_header.njk" %}

  <main>
    ...
  </main>

  {% include "_footer.njk" %}

</body>

3. 扩展/块

扩展 将包含提升到一个新的水平。扩展允许您定义一个模板文档,其中包含一些旨在接收内容块的“块”。

这是一个包含一些包含项的模板,但中间还有一个块

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>{{ page_title }}</title>
</head>

<body>

  {% include "parts/_header.njk" %}

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

  {% include "parts/_footer.njk" %}

</body>

</html>

现在任何其他文件都可以扩展该模板,而无需担心可能与网站所有页面相关的那些样板 HTML。例如,我们的 `index.njk` 变成了

{% extends "parts/_template.njk" %}

{% block main %}
  {% for feature in features %}
    <div class="module">
      <h3>{{ feature.name }}</h3>
      <p>{{ feature.description }}</p>
    </div>
  {% endfor %}
{% endblock %}

我敢打赌,您可以想象将其完善的样子。也许是针对不同类型页面的多个模板。更多块,为您提供了传入额外样式表或脚本的机会。更多用于网站区域的块,例如侧边栏和页脚中的内容。

4. 宏

说到将模板提升到一个新的水平, 再次做到了这一点。

宏就像带有参数的导入。就像函数!您提供一些值,它会为您返回一些内容。

想象一个接收三个值的模块。例如,“色板”(就像我们正在构建模式库),它接收颜色值、名称和注释。

我们可以这样构建它

{% macro cardSwatch(colorName, colorValue, colorNotes) %}
  <div class="color-swatch-tile">
    
    <div class="color-swatch"
         style="background-color: {{ colorValue }};">
    </div>
    
    <div class="color-name">
      {{ colorName }}
    </div>
    
    <div class="color-notes">
      {{ colorNotes }}
    </div>
    
  </div>
{% endmacro %}

现在我可以一遍又一遍地使用它

{{ cardSwatch("brandColor", "#f06d06", "Our main color.") }}
{{ cardSwatch("brandHighlight", "#d0b000", "For callouts and highlights.") }}
{{ cardSwatch("grayDark", "#333333", "For things like code block backgrounds.") }}

更好的是,我可以将宏移动到它们自己的文件/文件中,并在需要时导入它们。在这里,我将导入一个 macro扩展一个模板,并循环遍历 colors 数据调用一个 macro

{% from "macros/swatch.njk" import swatch %}

{% extends "parts/_template.njk" %}

{% block main %}

  {% for color in colors %}
    {{ swatch(color.color_name, color.color_value, color.color_notes) }}
  {% endfor %}

{% endblock %}

CodePen 项目支持 Nunjucks

确实如此!这很好,因为它不需要任何设置。(您知道 CodePen 项目 吗?)只需将文件名以 `.njk` 结尾,CodePen 就会知道将其作为 Nunjucks 处理。

这里有一个可以查看的示例。

使用 Gulp 的 Nunjucks

在本地使用 Nunjucks 时,您几乎肯定需要一个像 Gulp 这样的构建工具来帮助处理文件。幸运的是,有 gulp-nunjucks 使其变得更加容易。

gulp.task('default', () =>
  gulp.src('index.html')
    .pipe(nunjucks.compile({
      my_data: "is here"
    }))
    .pipe(gulp.dest('dist'))
);

仓库

我创建了一个,因为我在撰写本文时使用了 Nunjucks。

其他信息