模板入门

模板是一个文本文件,定义了输出文件的结构或布局,并使用占位符表示在渲染模板时(在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 子目录中搜索模板。

js
// 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 元素内部,等等。非嵌套元素(例如,单个段落)位于单独的行上。

pug
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 代码等效项,如 &gt;),以防止 JavaScript 注入或跨站点脚本攻击。

如果标签后跟等号,则后续文本将被视为 JavaScript 表达式。例如,在下面的第一行中,h1 标签的内容将是 变量 title(在文件中定义或从 Express 传递到模板中)。在第二行中,段落内容是一个文本字符串与 title 变量连接在一起。在这两种情况下,默认行为都是 转义该行。

pug
h1= title
p= 'Evaluated and <em>escaped expression</em>:' + title

注意:在 Pug 模板中,使用但未从 Express 代码(或本地定义)中传递的变量为“未定义”。如果你在没有传递 title 变量的情况下使用此模板,则会创建标签,但它们将包含空字符串。如果在条件语句中使用未定义的变量,则它们将计算为 false。其他模板语言可能要求在模板中使用的变量必须定义。

如果标签后面没有等号,则内容将被视为纯文本。在纯文本中,你可以分别使用 #{}!{} 语法插入转义和未转义的数据,如下所示。你也可以在纯文本中添加原始 HTML。

pug
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}.

注意:你几乎总是希望转义来自用户的(通过 #{} 语法)数据。可以信任的数据(例如,生成的记录计数等)可以在不转义值的情况下显示。

你可以在一行的开头使用管道 ('|') 字符来指示“纯文本”。例如,下面显示的附加文本将显示在前面锚点的同一行上,但不会链接。

pug
a(href='http://someurl/') Link text
| Plain text

Pug 允许你使用 ifelseelse ifunless 执行条件操作——例如

pug
if title
  p A variable named "title" exists
else
  p A variable named "title" does not exist

你还可以使用 each-inwhile 语法执行循环/迭代操作。在下面的代码片段中,我们循环遍历了一个数组以显示变量列表(请注意,下面使用 'li=' 将“val”计算为变量。你迭代的值也可以作为变量传递到模板中!

pug
ul
  each val in [1, 2, 3, 4, 5]
    li= val

语法还支持注释(可以根据你的选择在输出中渲染——或不渲染——),mixin 用于创建可重用的代码块,case 语句以及许多其他功能。有关更详细的信息,请参阅 Pug 文档

扩展模板

在整个站点中,所有页面通常都具有共同的结构,包括头部、页脚、导航等的标准 HTML 标记。为了避免开发人员在每个页面中重复此“样板代码”,Pug 允许你声明一个基本模板,然后扩展它,只替换每个特定页面中不同的部分。

例如,在我们的 框架项目 中创建的基本模板 layout.pug 如下所示

pug
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

block 标签用于标记可以在派生模板中替换的内容部分(如果未重新定义块,则使用基类中的实现)。

默认的 index.pug(为我们的框架项目创建)显示了我们如何覆盖基本模板。extends 标签标识要使用的基本模板,然后我们使用 block section_name 来指示我们将覆盖的部分的新内容。

pug
extends layout

block content
  h1= title
  p Welcome to #{title}

后续步骤