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="{"非常": "長的","數據": true}"/>
【轉義屬性】
默認情況下,所有的屬性都經過轉義(即把特殊字符轉換成轉義串行)來防止諸如跨站腳本攻擊之類的攻擊方式。 如果要使用特殊符號,需要使用 != 而不是 =。
<!-- pug -->
div(escaped="<code>")
div(unescaped!="<code>")
<!-- html -->
<div escaped="<code>"></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 支持使用 block 和 extends 關鍵字進行樣板的繼承。
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>