模板入門

模板是定義輸出檔案結構或佈局的文字檔案,其中包含佔位符,用於表示模板渲染時(在 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

該語法還支援註釋(可以渲染在輸出中,也可以不渲染——由你選擇)、混合(用於建立可重用程式碼塊)、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}

後續步驟