模板入门
模板是一个文本文件,定义了输出文件的结构或布局,并使用占位符表示在渲染模板时(在Express中,模板称为视图)将插入数据的位置。
Express 模板选择
Express 可以与许多不同的 模板渲染引擎 一起使用。在本教程中,我们使用 Pug(以前称为 Jade)作为我们的模板。这是最流行的 Node 模板语言,它将自己描述为“一种简洁、对空白敏感的语法,用于编写 HTML,深受 Haml 的影响”。
不同的模板语言使用不同的方法来定义布局和标记数据占位符——有些使用 HTML 定义布局,而另一些则使用可以转换为 HTML 的不同标记格式。Pug 属于第二种类型;它使用 HTML 的 表示,其中每一行中的第一个单词通常表示一个 HTML 元素,后续行的缩进用于表示嵌套。结果是一个可以直接转换为 HTML 的页面定义,但更简洁,并且可以说更容易阅读。
注意:使用 Pug 的一个缺点是它对缩进和空白敏感(如果在错误的位置添加了额外的空格,你可能会得到一个无用的错误代码)。但是,一旦你的模板到位,它们就非常容易阅读和维护。
模板配置
当我们 创建网站框架 时,LocalLibrary 已配置为使用 Pug。你应该在网站的 package.json 文件中看到 pug 模块作为依赖项包含在内,并在 app.js 文件中看到以下配置设置。这些设置告诉我们我们正在使用 pug 作为视图引擎,并且 Express 应该在 /views 子目录中搜索模板。
// View engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
如果你查看 views 目录,你会看到项目默认视图的 .pug 文件。这些包括主页的视图 (index.pug) 和我们需要用自己的内容替换的基本模板 (layout.pug)。
/express-locallibrary-tutorial //the project root /views error.pug index.pug layout.pug
模板语法
下面的示例模板文件展示了 Pug 的许多最有用的功能。
首先要注意的是,该文件映射了典型 HTML 文件的结构,(几乎)每一行中的第一个单词都是一个 HTML 元素,缩进用于指示嵌套元素。例如,body
元素位于 html
元素内部,段落元素 (p
) 位于 body
元素内部,等等。非嵌套元素(例如,单个段落)位于单独的行上。
doctype html
html(lang="en")
head
title= title
script(type='text/javascript').
body
h1= title
p This is a line with #[em some emphasis] and #[strong strong text] markup.
p This line has un-escaped data: !{'<em> is emphasized</em>'} and escaped data: #{'<em> is not emphasized</em>'}.
| This line follows on.
p= 'Evaluated and <em>escaped expression</em>:' + title
<!-- You can add HTML comments directly -->
// You can add single line JavaScript comments and they are generated to HTML comments
//- Introducing a single line JavaScript comment with "//-" ensures the comment isn't rendered to HTML
p A line with a link
a(href='/catalog/authors') Some link text
| and some extra text.
#container.col
if title
p A variable named "title" exists.
else
p A variable named "title" does not exist.
p.
Pug is a terse and simple template language with a
strong focus on performance and powerful features.
h2 Generate a list
ul
each val in [1, 2, 3, 4, 5]
li= val
元素属性在其关联元素之后用括号定义。在括号内,属性以逗号或空格分隔的属性名称和属性值对列表定义,例如
script(type='text/javascript')
、link(rel='stylesheet', href='/stylesheets/style.css')
meta(name='viewport' content='width=device-width initial-scale=1')
所有属性的值都经过 转义(例如,>
等字符被转换为其 HTML 代码等效项,如 >
),以防止 JavaScript 注入或跨站点脚本攻击。
如果标签后跟等号,则后续文本将被视为 JavaScript 表达式。例如,在下面的第一行中,h1
标签的内容将是 变量 title
(在文件中定义或从 Express 传递到模板中)。在第二行中,段落内容是一个文本字符串与 title
变量连接在一起。在这两种情况下,默认行为都是 转义该行。
h1= title
p= 'Evaluated and <em>escaped expression</em>:' + title
注意:在 Pug 模板中,使用但未从 Express 代码(或本地定义)中传递的变量为“未定义”。如果你在没有传递 title
变量的情况下使用此模板,则会创建标签,但它们将包含空字符串。如果在条件语句中使用未定义的变量,则它们将计算为 false
。其他模板语言可能要求在模板中使用的变量必须定义。
如果标签后面没有等号,则内容将被视为纯文本。在纯文本中,你可以分别使用 #{}
和 !{}
语法插入转义和未转义的数据,如下所示。你也可以在纯文本中添加原始 HTML。
p This is a line with #[em some emphasis] and #[strong strong text] markup.
p This line has an un-escaped string: !{'<em> is emphasized</em>'}, an escaped string: #{'<em> is not emphasized</em>'}, and escaped variables: #{title}.
注意:你几乎总是希望转义来自用户的(通过 #{}
语法)数据。可以信任的数据(例如,生成的记录计数等)可以在不转义值的情况下显示。
你可以在一行的开头使用管道 ('|') 字符来指示“纯文本”。例如,下面显示的附加文本将显示在前面锚点的同一行上,但不会链接。
a(href='http://someurl/') Link text
| Plain text
Pug 允许你使用 if
、else
、else if
和 unless
执行条件操作——例如
if title
p A variable named "title" exists
else
p A variable named "title" does not exist
你还可以使用 each-in
或 while
语法执行循环/迭代操作。在下面的代码片段中,我们循环遍历了一个数组以显示变量列表(请注意,下面使用 'li=' 将“val”计算为变量。你迭代的值也可以作为变量传递到模板中!
ul
each val in [1, 2, 3, 4, 5]
li= val
语法还支持注释(可以根据你的选择在输出中渲染——或不渲染——),mixin 用于创建可重用的代码块,case 语句以及许多其他功能。有关更详细的信息,请参阅 Pug 文档。
扩展模板
在整个站点中,所有页面通常都具有共同的结构,包括头部、页脚、导航等的标准 HTML 标记。为了避免开发人员在每个页面中重复此“样板代码”,Pug 允许你声明一个基本模板,然后扩展它,只替换每个特定页面中不同的部分。
例如,在我们的 框架项目 中创建的基本模板 layout.pug 如下所示
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
block
标签用于标记可以在派生模板中替换的内容部分(如果未重新定义块,则使用基类中的实现)。
默认的 index.pug(为我们的框架项目创建)显示了我们如何覆盖基本模板。extends
标签标识要使用的基本模板,然后我们使用 block section_name
来指示我们将覆盖的部分的新内容。
extends layout
block content
h1= title
p Welcome to #{title}
后续步骤
- 返回 Express 教程第 5 部分:显示库数据。
- 继续第 5 部分的下一篇文章:LocalLibrary 基本模板。