Pug: HTML 樣板引擎

如果你是常切版的前端工程師,pug 絕對是你要的。pug 原名為 jade,後來由於商標的關係而改名,但語法不變。

為什麼要使用 pug,對於手工撰寫 HTML 的工程師來說,往往會遇到過的的巢狀結構,開頭與結尾沒有收合,而造成程式錯誤。 而 pug 是使用縮排的階層關係,解決掉嵌套和成對 tag 的問題,而且可以讓沒有排版習慣的工程師,改善壞習慣。

<div>
  <div>
    <div>
      <div>
        <div>
          <div>
            多層巢狀結構  
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

結構語法

1. 標籤
【樹狀】

在默認情況下,在每行文本的開頭(或者緊跟白字符的部分)書寫這個 HTML 標籤的名稱。 使用縮進來表示標籤間的嵌套關係,這樣可以構建一個 HTML 代碼的樹狀結構。

<!-- pug -->
#nav
  ul.nav-list
    li
      a(herf="#") page     
    li
      a(herf="#") page    
    li
      a(herf="#") page    
    li
      a(herf="#") page
<!-- html -->
<div id="nav">
  <ul class="nav-list">
    <li><a herf="#">page</a></li>
    <li><a herf="#">page</a></li>
    <li><a herf="#">page</a></li>
    <li><a herf="#">page</a></li>
  </ul>
</div>

Pug可以使用像 CSS 的語法來使用 id 和 class ,而且你在使用 id 或 class 時,如果標籤使用的是 <div>,在 pug 中可以省略。 如果有其他的屬性時,使用方法是在標籤名稱後面加上括號。

【內聯】

為了節省空間, Pug 嵌套標籤提供了一種內聯式語法。

ul
  li: a(herf="#") page
  li: a(herf="#") page
  li: a(herf="#") page
  li: a(herf="#") page
【自閉合】

Pug 知道哪些元素是自閉合的,所以不需要加上 /,但也可以通過在自行加上 / 來明確聲明此標籤是自閉合的。

<!-- pug -->
img
input
img/
input/
<!-- html -->
<img/>
<input/>
<img/>
<input/>
2. 內容

Pug 提供了三種常用的方式來放置內容。

【管道文本】

這是最簡單的添加純文本的方法。只需要在每行前面加一個 | 字符,這個字符在類 Unix 系統下常用作「管道」功能,因此得名

<!-- pug -->
| 純文本當然也可以包括 
strong HTML
|  內容。
p
  | 但它必須單獨起一行。
<!-- html -->
純文本當然也可以包括 <strong>HTML</strong> 內容。
<p>但它必須單獨起一行。</p>
【標籤內文本】

最常用法,文本只需要和標籤名隔開一個空格。

<!-- pug -->
p 純文本當然也可以包括 <strong>HTML</strong> 內容。
<!-- html -->
<p>純文本當然也可以包括 <strong>HTML</strong> 內容。</p>
【嵌入大段文本】

有時可能想要寫一個大段文本塊。比如嵌入腳本或者樣式。只需在標籤後面接一個 .

<!-- pug -->
p.
  有時可能想要寫一個大段文本塊。
  比如嵌入腳本或者樣式。
<!-- html -->
<p>
  有時可能想要寫一個大段文本塊。比如嵌入腳本或者樣式。
</p>
3. 屬性

標籤屬性和 HTML 語法非常相似,它們的值就是普通的 JavaScript 表達式。

<!-- pug -->
a(href='google.com') Google
a(class='button' href='google.com') Google
a(class='button', href='google.com') Google
<!-- html -->
Google
Google
Google

可以用逗號作為屬性分隔符,也可以不加逗號。

【多行屬性】

如果有很多屬性,可以把它們分幾行寫。

<!-- pug -->
input(
  type='checkbox'
  name='agreement'
  checked
)
<!-- html -->
<input type="checkbox" name="agreement" checked="checked"/>
【長屬性】

如果有一個很長的屬性,並且 JavaScript 運行時引擎支持 ES6 字符串,可以使用它來寫屬性值。

<!-- pug -->
input(data-json=`
  {
    "非常": "長的",
    "數據": true
  }
`)
<!-- html -->
<input data-json="{&quot;非常&quot;: &quot;長的&quot;,&quot;數據&quot;: true}"/>
【轉義屬性】

默認情況下,所有的屬性都經過轉義(即把特殊字符轉換成轉義串行)來防止諸如跨站腳本攻擊之類的攻擊方式。 如果要使用特殊符號,需要使用 != 而不是 =

<!-- pug -->
div(escaped="<code>")
div(unescaped!="<code>")
<!-- html -->
<div escaped="&lt;code&gt;"></div>
<div unescaped="<code>"></div>

【注意】未經轉義的緩存代碼十分危險。必須正確處理和過濾用户的輸入來避免跨站腳本攻擊。

【行內樣式】

style(樣式)屬性可以是一個字符串(就像其他普通的屬性一樣)還可以是一個對象。

<!-- pug -->
<!-- html -->
【類別 和 ID】

類別可以使用 .classname 語法來定義,ID 可以使用 #idname 語法來定義 考慮到使用 div 作為標籤名這種行為實在是太常見了,所以如果省略掉標籤名稱的話,它就是默認值。

<!-- pug -->
a.button
.content
a#main-link
#content
<!-- html -->
<a class="button"></a>
<div class="content"></div>
<a id="main-link"></a>
<div id="content"></div>
4. 註釋

單行註釋和 JavaScript 類似,但是必須獨立一行。

<!-- pug -->
// 單行註釋
//- 不輸出註釋
//
  塊註釋
  隨便寫多少字
  都沒關係。

邏輯語法

邏輯語法有 JS代碼、變數、流程控制、循環、mixin、include,其他的跟 JS 語法差不多這邊只提後面兩個。

1. mixin 混入

mixin 能重用程式碼,而且維護簡單,可以理解為 function ,是一種允許在 Pug 中重複使用一整個代碼塊的方法。

<!-- pug -->
//- 定義
mixin list
  ul
    li foo
    li bar
    li baz
//- 使用
+list
+list
<!-- html -->
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>

帶參數的 mixin:

<!-- pug -->
mixin pet(name)
  li.pet= name
ul
  +pet('貓')
  +pet('狗')
  +pet('豬')
<!-- html -->
<ul>
  <li class="pet">貓</li>
  <li class="pet">狗</li>
  <li class="pet">豬</li>
</ul>

混入也可以把一整個代碼塊像內容一樣傳遞進來。

<!-- pug -->
mixin article(title)
  .article
    .article-wrapper
      h1= title
      if block
        block
      else
        p 沒有提供任何內容。
+article('Hello world')
+article('Hello world')
p 這是我
p 隨便寫的文章
<!-- html -->
<div class="article">
  <div class="article-wrapper">
    <h1>Hello world</h1>
    <p>沒有提供任何內容。</p>
  </div>
</div>
<div class="article">
  <div class="article-wrapper">
    <h1>Hello world</h1>
    <p>這是我</p>
    <p>隨便寫的文章</p>
  </div>
</div>
2. include

包含(include)功能允許把另外的文檔內容插入進來。

//- index.pug
doctype html
html
  include includes/head.pug
  body
    h1 我的網站
    p 歡迎來到我這簡陋得不能再簡陋的網站。
    include includes/foot.pug

//- includes/head.pug
head
  title 我的網站
  script(src='/javascripts/jquery.js')
  script(src='/javascripts/app.js')

//- includes/foot.pug
footer#footer
  p Copyright (c) foobar

被包含的如果不是 Pug 文檔,那麼就只會當作文本內容來引入。

3. 文件繼承

Pug 支持使用 blockextends 關鍵字進行樣板的繼承。

block 塊就是定義一段 html 程式碼,hello 就是我們定義的 block 塊,定義好之後我們可以直接通過block hello 呼叫從而實現程式碼的複用。

<!-- pug -->
block hello
  p luckyw.cn
  
block hello
<!-- html -->
<p>luckyw</p>

block 真正的作用在於佔位,供子檔案繼承,例如每個檔案的 head 頁頭都一樣,就 body 裡內容不一樣,可以寫一個 layout.pug 檔案。

//- layout.pug
doctype
html
head
  title Document
body
  block content

然後改寫 index.pug,首先用 extends 繼承自 layout.pug 的,然後重寫 layout.pug 裡的 block content

//- index.pug
extends layout.pug

block content
  p this is content
<!DOCTYPE html>
<html>
  <head>
    <title>Document</title>
  </head>
  <body>
    <p>this is content</p>
  </body>
</html>
TOP