用NodeJS模板引擎构建视图的方法
模板引擎使渲染视图变得容易,无论是电子邮件、屏幕还是其他任何东西。
作为现代的网络开发者,用API构建动态网站是我们都很熟悉的事情。特别是Node.js,使得快速建立API后端并将其与客户端的Web应用连接起来变得非常容易。但你知道吗,Node允许应用模板引擎作为渲染网页的另一种方式?
相对于基于API的网站建设方式,模板引擎允许你在服务器端呈现动态内容的页面。当你在处理那些严重依赖从数据库中获取数据的页面时,它们提供了灵活性。特别是在建设静态网站时,模板引擎可以通过实现代码重用来改善开发过程。
就像它的名字一样,基于模板引擎的网站的主要构建块是模板。每个页面模板使用特殊的语法和变量来定义一个网页的基本结构。当最后渲染页面的时候,你可以通过这些变量的准确值来创建一个具有针对每个请求的细节的页面。
在Node.js中,开发者有机会从几十个不同的可用选项中挑选一个模板引擎。其中最受欢迎的包括:
- Pug
- EJS
- Handlebars
- Nunjacks
- 道特
- 小胡子
- 不倒翁
- 马尔科
在今天的文章中,我们将讨论上述列表中的前四个模板引擎,Pug、EJS、Handlebars和Nunjacks,让你了解到如何使用模板引擎,并利用它们来构建令人难以置信的强大网页。
Pug
Pug,以前被称为Jade,是Node中最常用的模板引擎之一。它提供了一种基于缩进的语法来向页面添加内容。使用Pug,你可以在代码中使用多种控制结构,包括条件语句和循环。
下面是我们在Pug和Bootstrap CSS的帮助下创建的一个简单网页。
doctype html
html
head
meta(name='viewport', content='width=device-width')
link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css")
title Home Page
body
div.navbar.navbar-expand.navbar-light.bg-warning
ul.navbar-nav.mb-2
li.nav-item
a.nav-link(href="/") Home
each field in fields
li.nav-item
a.nav-link(href="/"+field.name) #{field.name}
div.container.text-left.mt-3
h1 Welcome to our website, #{user}
div.message
p Find anything you want on our website.
正如你所看到的,Pug直接使用HTML元素名称,而不在其语法中包含标签。然后,它使用缩进来推导层次结构,将缩进的元素视为上层元素的子女。
给一个元素指定一个CSS类,就像用前面的点来声明它们的名字一样简单。
div.navbar
你也可以把一个元素的类作为一个普通的属性来添加。它让你可以自由地编写Javascript来决定属性的值。
div(class=logged ? "logged" : "anon")
我们已经按照类似的逻辑添加了锚标签的URL。
a(href="/"+field.name)
访问变量
我们的Pug模板使用两个变量,字段和用户,来创建页面结构。在模板内访问它们的值可以有两种方式。
如果变量值是分配给一个HTML元素或属性的唯一内容,我们可以使用等号来完成工作。
title=titlevar
否则,我们可以使用#{var}语法来访问变量值。这是我们的例子中多次使用过的方法。
h1 Welcome to our website, #{user}
在数组上循环操作
我们可以用下面的语法在Pug模板中遍历一个数组变量。
each field in fields
li.nav-item
a.nav-link(href="/"+field.name) #{field.name}
在Express中渲染Pug模板
流行的Node.js框架,Express,提供了一套专门的方法来介绍和使用Web应用服务器端的模板引擎。为此,我们将首先把我们的Pug模板放在一个扩展名为.pug的文件中,并将其存储在项目文件夹中一个名为views的目录中。让我们给我们的模板文件起个名字,叫index.pug。
然后,我们可以使用npm在我们的项目中安装Pug。
npm install pug
现在,我们可以在我们的初始应用代码中设置视图引擎和专用的视图目录。
//app.js
const express = require("express");
const path = require("path");
const app = express();
//Set view engine name and template directory path
app.set("view engine", "pug");
app.set("views", path.join(__dirname, "views"));
app.listen(3000 || process.env.PORT, () => {
console.log("Server started listening");
});
最后,我们应该为来到我们的Web应用的"/"路线的请求渲染index.pug文件。
fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];
app.get("/", (req, res) => {
const username = req.query.username;
res.render("index", {user: username, fields: fields});
});
注意我们是如何将变量值作为参数传递给渲染方法的。这将允许Pug用它们的实际值替换变量名,并渲染最终的HTML内容。
当我们启动Node应用程序并访问URL,"localhost:3000?username=Smith "时,我们可以在网页上看到以下渲染的内容。

用NodeJS模板建立的演示网站
添加参数
参数是当今大多数模板引擎为重复使用代码片段提供的一个特殊功能。它们允许我们单独声明重复使用的组件,并在其他模板中重复包含它们。
在我们的例子中,导航条是我们在应用程序中创建不同页面时需要重复使用的一个组件。因此,我们可以为导航条创建一个局部,使其更容易被重用,而不是在每个页面文件中重写其代码的痛苦。
让我们为导航条创建一个单独的模板文件,名为navbar.pug。
//views/navbar.pug
div.navbar.navbar-expand.navbar-light.bg-warning
ul.navbar-nav.mb-2
li.nav-item
a.nav-link(href="/") Home
each field in fields
li.nav-item
a.nav-link(href="/"+field.name) #{field.name}
在我们的索引页中使用这个局部就像使用一个名为 "include "的特殊关键字一样简单。
//views/index.pug
body
include navbar
div.container.text-left.mt-3
h1 Welcome to our website, #{user}
div.message
p Find anything you want on our website.
Handlebars
Handlebars是Node中另一个流行的模板引擎Mustache的一个扩展。与Pug不同,Handlebars和Mustache都是无逻辑的模板引擎:它们不支持模板代码中基于逻辑的条件或循环。它迫使你将逻辑与页面的表现形式分开,使代码库更容易测试和维护。
Handlebars与Pug的另一个区别是,它使用常规的HTML语法来构建页面结构,而不是依赖缩进。我们在下面展示了如何使用Handlebars的语法创建一个与上一个页面内容相同的页面。由于其语法更接近于HTML,用Handlebars建立模板是相当直观的。
{{!-- views/index.hbs --}}
<!DOCTYPE html>
<html>
<head>
<meta name='viewport', content='width=device-width'/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
<title>Home Page</title>
</head>
<body>
<div class="navbar navbar-expand navbar-light bg-warning">
<ul class="navbar-nav mb-2">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
{{#each fields}}
<li class="nav-item">
<a class="nav-link" href="/{{name}}">{{name}}</a>
</li>
{{/each}}
</ul>
</div>
<div class="container text-left mt-3">
<h1>Welcome to our website, {{user}}</h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
</html>
在Handlebars中访问变量时,我们应该用两边的大括号把变量名称括起来。
<h1>Welcome to our website, {{user}}</h1>
Handlebars还支持用以下语法在数组中进行迭代。
{{#each fields}}
<li class="nav-item">
<a class="nav-link" href="/{{name}}">{{name}}</a>
</li>
{{/each}}
在每个类似迭代的帮助器内,我们可以直接访问存储在数组中的每个对象的属性。
用 Express 渲染 Handlebars 模板
要在Express中使用Handlebars,首先,我们应该用npm安装它。
npm install hbs
然后,设置Handlebars作为视图引擎和渲染模板页面的过程与我们对Pug所做的类似步骤。
//app.js
const express = require("express");
const path = require("path");
const app = express();
app.set("view engine", "hbs");
app.set("views", path.join(__dirname, "views"));
fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];
app.get("/", (req, res) => {
const username = req.query.username;
res.render("index", {user: username, fields: fields});
});
app.listen(3000 || process.env.PORT, () => {
console.log("Server started listening");
});
添加参数
在Handlebars中,在模板中使用参数之前,我们必须先注册这些参数。为此,让我们首先在视图目录下创建一个名为 "partials "的单独目录,以存储参数文件。
在partials目录中,我们在一个名为navbar.hbs的文件中添加导航条组件的代码。
{{! views/partials/navbar.hbs}}
<div class="navbar navbar-expand navbar-light bg-warning">
<ul class="navbar-nav mb-2">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
{{#each fields}}
<li class="nav-item">
<a class="nav-link" href="/{{name}}">{{name}}</a>
</li>
{{/each}}
</ul>
</div>
然后,我们就可以在应用程序代码里面注册这个partials目录。
const hbs = require("hbs");
hbs.registerPartials(path.join(__dirname, "views/partials"));
现在,当我们在模板中包含部分组件时,Handlebars会识别它并导入组件代码来渲染网页。
<body>
{{>navbar}} {{! including the partial}}
<div class="container text-left mt-3">
<h1>Welcome to our website, {{user}}</h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
EJS
EJS是另一个流行的Node.js模板引擎,使用类似HTML的语法。它允许你在模板内使用带有变量和编程逻辑的普通Javascript,以控制其结构。
EJS提供了一组标签,用于在模板中包含Javascript代码。每个独特的标签决定了所包含的代码如何影响模板的最终渲染输出。在这里,我们列出了一些你在用EJS创建网页时经常会用到的标签:
<%使用条件语句、循环等处理代码的控制流。它不向模板输出任何值。<%=将标签内计算的值输出到模板。它转义任何HTML代码。<%-输出一个未转义的值到模板上。<%#评论标签
现在,让我们看看如何将Node应用程序的主页转换成EJS模板。
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
<meta name='viewport', content='width=device-width'/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
<title>Home Page</title>
</head>
<body>
<div class="navbar navbar-expand navbar-light bg-warning">
<ul class="navbar-nav mb-2">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<% fields.forEach(field => { %>
<li class="nav-item">
<a class="nav-link" href=<%= "/"+ field.name %>><%= field.name %></a>
</li>
<% }) %>
</ul>
</div>
<div class="container text-left mt-3">
<h1>Welcome to our website, <%= user %></h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
</html>
正如你在这段代码中看到的,EJS使用HTML语法来构建基本模板。然后,从访问变量到迭代数组的所有内容都是使用我们之前讨论过的特殊标签内声明的常规Javascript代码执行的。
用Express渲染EJS模板
渲染过程与我们之前使用模板引擎时的路径相似。首先,我们使用npm安装EJS。
npm install ejs
然后,将EJS设置为应用程序的视图引擎,在将其发送给客户端之前,用变量值渲染index.ejs。
//app.js
const express = require("express");
const path = require("path");
const app = express();
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];
app.get("/", (req, res) => {
const username = req.query.username;
res.render("index", {user: username, fields: fields});
});
app.listen(3000 || process.env.PORT, () => {
console.log("Server started listening");
});
添加参数
用EJS添加参数与我们用Pug实现的方法类似。我们首先创建一个新的partials文件,即views/partials/navbar.ejs,其中包含navbar代码。然后,我们可以像这样在主页的主模板中包含该部分。
<!-- views/index.ejs -->
<body>
<%- include ("partials/navbar") %>
<div class="container text-left mt-3">
<h1>Welcome to our website, <%= user %></h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
Nunjucks
Nunjucks是一个由Mozilla建立的强大的模板引擎,你可以在Node.js中使用。它的速度很快,在渲染网页时允许异步加载内容。它支持类似于Handlebars和EJS的HTML语法,并使用一个特殊的{% %}标签来声明控制操作。
让我们在下面的例子中看看如何将我们的网页转换成Nunjucks模板。
{# views/index.njk #}
<!DOCTYPE html>
<html>
<head>
<meta name='viewport', content='width=device-width'/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"/>
<title>Home Page</title>
</head>
<body>
<div class="navbar navbar-expand navbar-light bg-warning">
<ul class="navbar-nav mb-2">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
{% for field in fields %}
<li class="nav-item">
<a class="nav-link" href="/{{field.name}}">{{field.name}}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="container text-left mt-3">
<h1>Welcome to our website, {{ user }}</h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
</html>
正如这个代码片段所示,Nunjucks允许我们在带有双括号的标签内访问变量。当定义控制操作(如for loops)时,我们应该使用{% %}标签,并遵循其官方模板文件中规定的语法。
用Express渲染Nunjucks模板
我们可以用npm轻松安装Nunjucks。
npm install nunjucks
渲染Nunjucks模板与我们在前几节所做的有些不同:除了设置视图引擎和渲染页面外,我们还必须遵循Nunjucks的配置步骤。
//app.js
const express = require("express");
const path = require("path");
const nunjucks = require("nunjucks");
const app = express();
app.set('view engine', 'njk');
//configure Nunjucks by passing the express app and setting autoescape to true
nunjucks.configure('views', {
autoescape: true,
express: app
})
fields = [{name: "Technology"}, {name: "News"}, {name: "Sports"}, {name: "Travel"}];
app.get("/", (req, res) => {
const username = req.query.username;
res.render("index", {user: username, fields: fields});
});
app.listen(3000 || process.env.PORT, () => {
console.log("Server started listening");
});
添加参数
在Nunjucks中添加参数,就像我们在以前的模板工具中一样执行。将导航条代码添加到partials文件夹中一个名为 "navbar.njk "的新文件后,我们可以使用include关键字将其添加到主页模板中。
<body>
{% include "partials/navbar.njk" %}
<div class="container text-left mt-3">
<h1>Welcome to our website, {{ user }}</h1>
<div class="message">
<p>Find anything you want on our website.</p>
</div>
</div>
</body>
总结
在今天的文章中,我们谈到了使用模板引擎与Node.js来构建Web应用程序。我希望这篇文章是对Node模板引擎的一个很好的介绍。如果你已经有了使用它们的经验,请在我们的评论区告诉我们你最喜欢的模板引擎。