Node 學習 -- jade

小諾哥發表於2017-04-03

jade(pug)

由於商標版權問題,Jade 已經改名為了 Pug,github地址github.com/pugjs/pug

Jade 是一個高效能的模板引擎,它是用 JavaScript 實現的,並且可以供 Node 使用,當然還支援其他語言。

檔案字尾名為.pug(.jade)

jade優點

  • 可讀性高
  • 靈活的縮排
  • 塊展開
  • 程式碼預設經過編碼處理(轉義),安全性高
  • 執行時和編譯時上下文錯誤報告
  • 支援命令列編譯
  • 支援html5模式
  • 在記憶體中快取(可選)
  • 原生支援 Express
  • 合併動態和靜態標籤類
  • 過濾器

關於Ejs或者其他模板引擎與jade比較,可以看看這篇文章www.zhihu.com/question/20…

安裝

npm安裝建議安裝個nrm來進行源管理.

npm install pug -g
npm install pug-cli -g複製程式碼

測試demo

為了方便編寫程式碼,最好把編譯器的tab設定:2.

// index.jade

doctype html
html
  head
    title jade test
  body
    h2 jade study複製程式碼
粗暴的編譯方法
pug index.jade

// index.html
<!DOCTYPE html><html><head><title>jade test</title></head><body><h2>jade study    </h2></body></html>複製程式碼

發現編譯後的程式碼不具備可讀性.

pug -- help
 Options:
     -P, --pretty           compile pretty HTML output ## 輸出漂亮結構的HTML
    -D, --no-debug         compile without debugging (smaller functions) ## 不帶除錯的編譯
    -w, --watch            watch files for changes and automatically re-render ## 對某個檔案的變動保持監控
    -E, --extension <ext>  specify the output file extension ## 指定輸出副檔名
    -s, --silent           do not output logs ## 不輸出日誌複製程式碼
// 重新編譯
pug -P index.jade
<!DOCTYPE html>
<html>
  <head>
    <title>jade test</title>
  </head>
  <body>
    <h2>jade study    </h2>
  </body>
</html>複製程式碼
自動編譯

只是為了學習,這裡只要設定-w -P .開發中通過打包工具來進行自動編譯.

// 命令列工具推薦使用Cmder

λ pug -P -w index.jade
  watching index.jade
  rendered index.html複製程式碼

Express與Pug

Pug完全整合了一個流行的Node.js Web框架Express,作為支援的檢視引擎。 看看Express是如何將Pug與Express整合的完美指南。

在Express中,環境變數NODE_ENV旨在向Web應用程式通知執行環境:無論是在開發中還是在生產中。 Express和Pug自動修改生產環境中的幾個選項的預設值,為使用者提供更好的開箱即用體驗。 具體來說,當process.env.NODE_ENV設定為“production”,Pug與Express一起使用時,compileDebug選項預設為false,而cache選項為true。

API

標籤屬性
  • id,class寫法
// 編譯前

  p.title class寫法1
  p(class='title') class寫法2
  p#tit id寫法1
  p(id='tit2') id寫法2     

// 編譯後
  <p class="title">class寫法1</p>
  <p class="title">class寫法2</p>
  <p id="tit">id寫法</p>
  <p id="tit2">id寫法2 </p>複製程式碼
// 編譯前
- var classArr = ['small','medium','large']
a(class= classArr)
a.test(class = classArr class=['add'])

// 編譯後
<a class="small medium large"></a>
<a class="test small medium large add"></a>複製程式碼

它也可以是將類名對映到true或false值的物件.

//編譯前
- var active = 'select'
a(class={active: active === 'select'} )

// 編譯後
<a class="active"></a>複製程式碼
  • 其他屬性
    通過()來依次編寫屬性,多個用逗號隔開.
//編譯前
a(class='baidu' ,title='baidu' href='www.baidu.com') 百度

//編譯後
<a class="baidu" title="baidu" href="www.baidu.com">百度</a>複製程式碼
  • 也支援所有正常的javascript表示式
// 編譯前
- var flag  = true   //注意這裡使用變數要記得新增-符號.
h2(class=flag ? 'flag': '')

// 編譯後
<h2 class="flag"></h2>複製程式碼
  • 多個屬性的另外寫法

其實就是換號縮排

// 編譯前
a(
      title='baidu',
      href='www.baidu.com',
      class='links'
)
// 編譯後
<a class="links" title="baidu" href="www.baidu.com"></a>複製程式碼

如果您有一個非常長的屬性,並且您的JavaScript執行時支援ES2015模板字串,則可以使用該語法的屬性:

// 編譯前
input(data-json=`
      {
        "very-long": "piece of ",
        "data": true
      }
`)
// 編譯後
<input data-json="
      {
        &quot;very-long&quot;: &quot;piece of &quot;,
        &quot;data&quot;: true
      }
">複製程式碼
  • 引用屬性

如果你的屬性名稱包含了與JavaScript語法衝突的字元,請使用""或''引用,或使用逗號分隔不同的屬性。

官網舉了個Angular 2的例子.

//(click)='play()',這裡(click)會被當作一個函式呼叫而不是一個屬性名字來解析.

// 編譯前
div(class='div-class' (click)='play()')

// 編譯後報錯
div(class='div-class' (click)='play()')
---------------------^複製程式碼

正確寫法

// 編譯前
div(class='div-class' '(click)'='play()')
div(class='div-class', (click) = 'play()')

// 編譯後
<div class="div-class" (click)="play()"></div>
<div class="div-class" (click)="play()"></div>複製程式碼
  • 屬性插值

以前版本的Pug / Jade支援如下插值語法(不再支援):

//編譯前
- var url = 'www.baidu.com'
a(href='/#{url}') links

//編譯後 已不再支援
<a href="/#{url}">links</a>複製程式碼

新的寫法

// 編譯前
- var url = 'demo.com'
a(href='/' + url) links
- var url2 = 'www.baidu.com'
a(href = url2 ) 百度  

// 編譯後
<a href="/demo.com">links</a>
<a href="www.baidu.com">百度  </a>複製程式碼

如果你的javascript執行環境支援ES 2015.那麼Pug支援模板字串語法

// 編譯前
- var size1 = 'small'
- var size2 = 'medium'
- var size3 = 'large'
button(
  type='button',
  class='btn btn-' + size1 + ' ' +  'btn-' + size2 + ' ' + 'btn-' + size3
)
button(
  type='button',
  class=`btn btn-$(size1) btn-$(size2) btn(size3)`
)
// 編譯後
<button class="btn btn-small btn-medium btn-large" type="button"></button>
<button class="btn btn-small btn-medium btn-large" type="button"></button>複製程式碼
  • 未轉義屬性

預設情況下,會轉義所有屬性(用轉義序列代替特殊字元),以防止諸如跨站點指令碼之類的攻擊。 如果必須需要使用特殊字元,可以使用!=而不是=。

// 編譯前
div(title="<code>")
div(title!="<code>")

// 編譯後
<div title="&lt;code&gt;"></div>
<div title="<code>"></div>複製程式碼
  • 布林屬性

布林屬性由Pug映象,並接受布林值(true和false)。 當沒有指定值時,預設為true。

// 編譯前
input(type='radio' checked)
input(type='radio' checked=true)
input(type='radio' checked=false)

// 編譯後
<input type="radio" checked>
<input type="radio" checked>
<input type="radio">複製程式碼
  • style屬性

style屬性可以是一個字串(像任何普通屬性),但它也可以是一個物件

// 編譯前
p(style={fontSize: '14px',color: 'red'})

// 編譯後
<p style="fontSize:14px;color:red;"></p>複製程式碼
Case

case語句是JavaScript Switch語句的縮寫,並採用以下形式:

// 編譯前
- var friendsNum = 4
    case friendsNum
      when 0
        p you have not friend
      when 1
        p you has one friend
      default
        p you has #{friendsNum} friends    

// 編譯後
<p>you has 4 friends    </p>複製程式碼
// 編譯前
- var friendsNum = 1
    case friendsNum
      when 0
      when 1
        p you has one friend
      default
        p you has #{friendsNum} friends

// 編譯後
<p>you has one friend</p>複製程式碼

當然也支援break;

// 編譯前

- var friendsNum = 0
    case friendsNum
      when 0
        - break
      when 1
        p you has one friend
      default
        p you has #{friendsNum} friends

// 編譯後
無內容複製程式碼

也可以使用塊擴充套件語法

// 編譯前
  - var friendsNum = 1
    case friendsNum
      when 0
      when 1: p you has one friend
      default: p you has #{friendsNum} friends

// 編譯後
<p>you has one friend</p>複製程式碼
Code

Pug可以在你的模板中編寫內建的JavaScript程式碼。 有三種型別的程式碼。

  • Unbuffered Code
    不直接新增任何的輸出
// 編譯前
- for(var i = 0; i < 3;i++)
      li item

// 編譯後
<li>item</li>
<li>item</li>
<li>item</li>複製程式碼
// 編譯前

- var nameList = ['kobe','cpul','james']
      each item in nameList
        li=item

// 編譯後

<li>kobe</li>
<li>cpul</li>
<li>james</li>複製程式碼
  • Buffered Code

以=開頭,並輸出評估模板中JavaScript表示式的結果。 為了安全起見,首先HTML被轉義:

// 編譯前

p
  = 'this is code template <code>'
p= 'this is code template' + '<code>'  

// 編譯後

<p>this is code template &lt;code&gt;
</p>
<p>this is code template&lt;code&gt;</p>複製程式碼
  • Unescaped Buffered Code

未轉義的程式碼以!=開頭,並輸出評估模板中JavaScript表示式的結果。 這不會進行任何轉義,所以對使用者輸入是不安全的:

// 編譯前
p
  != 'this is code template <code>'
p!= 'this is code template' + '<code>'  

// 編譯後
<p>this is code template <code>
</p>
<p>this is code template<code></p>複製程式碼
Comments註釋
  • 單行註釋
// 編譯前

// 這是一個註釋
p 這是一個註釋

// 編譯後

<!-- 這是一個註釋-->
<p>這是一個註釋</p>複製程式碼

Pug還有種註釋寫法,只需新增連字元'-'即可。這些僅用於對Pug程式碼本身進行註釋,編譯後不會出現在HTML中。

// 編譯前

//- 這是一個註釋
p 這是一個註釋

// 編譯後
<p>這是一個註釋</p>複製程式碼
  • 塊級註釋
// 編譯前

//-
  註釋不會出現在模板中
  真的
//
  第一行註釋
  第二行註釋

// 編譯後

<!--
    第一行註釋
    第二行註釋
-->複製程式碼
  • 條件註釋

對於條件註釋,Pug沒有任何特殊的語法,下面例子這是為舊版本的Internet Explorer新增後備標記的特殊方法,但是由於以<開頭的所有行被視為純文字,普通的HTML樣式條件註釋將會很好。

// 編譯前
<!--[if IE 8]>
<p class="lt-ie9">
<![endif]-->

// 編譯後

<!--[if IE 8]>
<p class="lt-ie9">
<![endif]-->複製程式碼
Conditionals條件語句
// 編譯前
- var user = {name: 'kobe'}
- var flag = true
#user
  if user.name
    h3.user-title #{user.name}
  else if flag
    p flag is #{flag}
  else
    p default   

// 編譯後
<div id="user">
  <h3 class="user-title">kobe</h3>
</div>複製程式碼

Pug也支援另外一個關鍵字 unless

// 編譯前
- var user = {name: 'kobe'}
#user
  unless !user.name
  h2 #{user.name}


// 編譯後
<div id="user">
  <h2>kobe</h2>
</div>複製程式碼
doctype
// 編譯前

doctype html

// 編譯後

<!DOCTYPE html>複製程式碼
Filters過濾器

過濾器可讓你在Pug模板中使用其他語言。也就是支援外掛的使用,通過外掛對模板內容進行過濾,處理,輸出.如scss,less,markdown,coffee-script....

先全域性安裝這些外掛

npm install --save jstransformer-coffee-script
npm install --save jstransformer-markdown-it複製程式碼
// 編譯前

h2 MarkDown
  :markdown-it
    #### this is markdown filter
    [link](http://www.baidu.com)

  :coffee-script
    console.log('this is coffee-script');

// 編譯後

<h2>MarkDown</h2><h4>this is markdown filter</h4>
<p><a href="http://www.baidu.com">link</a></p>
    (function() {
  console.log('this is coffee-script');

}).call(this);複製程式碼

缺點:不能支援動態內容或選項。

Includes包含

Pug允許你靜態包含一段 Jade, 或者別的存放在單個檔案中的東西比如 CSS, HTML 非常常見的例子是包含頭部和頁尾。 假設我們有一個下面目錄結構的資料夾:

- /index.jade
- /includes/
  -/head.jade
  -/footer.jade複製程式碼
// index.jade
doctype html
html
  include includes/header.jade
  body
    h1 這是主題內容
    include includes/footer.jade複製程式碼
// header.jade
header
  title 通用的header
  script(src='/jQuery.js')
  link(href='reset.css')複製程式碼
// footer.jade
footer#footer
  p Copyright (c) foobar複製程式碼
// 編譯後
<!DOCTYPE html>
<html>
  <header>
    <title>通用的header</title>
    <script src="/jQuery.js"></script>
    <link href="reset.css">
  </header>
  <body>
    <h1>這是主題內容</h1>
    <footer id="footer">
      <p>Copyright (c) foobar</p>
    </footer>
  </body>
</html>複製程式碼

include 可以包含比如 HTML 或者 CSS 這樣的內容。給定一個副檔名後,Jade 不會把這個檔案當作一個 Jade 原始碼,並且會把它當作一個普通文字包含進來:

// 格式

style
  include style.css
script
  include script.js複製程式碼

甚至可以通過include結合過濾器使用

// 引入article.md
include:markdown-it article.md複製程式碼
模板繼承

Jade 支援通過 block 和 extends 關鍵字來實現模板繼承。 一個塊就是一個 Jade 的 block ,它將在子模板中實現,同時是支援遞迴的。

如果需要,Pug block 可以提供預設內容,但是可以通過block scripts, block content, 和 block foot來顯示如下所示的可選項。

// 基本使用

// 編譯前
block desc
  p 這是block context
block desc  

// 編譯後
<p>這是block context</p>複製程式碼
// index.jade

doctype html
html
  include includes/header.jade
  body
    block content
    block foot
    .footer  some footer content複製程式碼

現在要繼承上面那個index.jade,只需建立一個新檔案,並使用extend指令,如下所示,給出路徑。 您現在可以定義一個或多個block將覆蓋父塊內容的塊.

在Pug v1中,如果沒有給定副檔名,那麼.pug會自動附加到路徑上,但是在Pug v2中,這個行為已被棄用。

// index.jade

doctype html
html
  block scripts
    script(src='/jquery.js')
  body
    block content
    block foot
    .footer  some footer content複製程式碼
// page.jade

extends index.jade

block scripts
  script(src='/jquery.js')
  script(src='/page.js')

block content
  h2 page.jade
  - var pets = ['cat', 'dog']
  each petName in pets
    li=petName複製程式碼
// page.jade 編譯後

<!DOCTYPE html>
<html>
  <script src="/jquery.js"></script>
  <script src="/page.js"></script>
  <body>
    <h2>page.jade</h2>
    <li>cat</li>
    <li>dog</li>
    <div class="footer"> some footer content</div>
  </body>
</html>複製程式碼

同樣可以在一個子塊裡繼續新增塊,就像下面實現的塊 content 裡又定義了兩個可以被實現的塊 sidebar 和 primary,或者子模板直接實現 content。

block content
  .sidebar
    block sidebar
      p nothing
  .primary
    block primary
      p nothing複製程式碼

Pug允許你 替換 (預設)、 前置 和 追加 blocks. 使用 block append 或 block prepend 時 block 是可選的:

// pageTwo.jade

extend page.jade

append scripts
  script(src='/pageTwo.js')複製程式碼
// 編譯後

<!DOCTYPE html>
<html>
  <script src="/jquery.js"></script>
  <script src="/page.js"></script>
  <script src="/pageTwo.js"></script>
  <body>
    <h2>page.jade</h2>
    <li>cat</li>
    <li>dog</li>
    <div class="footer"> some footer content</div>
  </body>
</html>複製程式碼
Interpolation插值
// 編譯前
- var author = 'xyz'
- var date = '2017-4'
h2
  p writer was by #{author.toUpperCase()}
  p date is #{date}

// 編譯後

<h2>
  <p>writer was by XYZ</p>
  <p>date is 2017-4</p>
</h2>複製程式碼

如果你想保持#{}插值符號,可以使用#{或者'\'.

Iteration迭代
  • each
// 編譯前
- var arr = [1,2,3,4]
each val,index in arr
  li= index + ':' + val 

// 編譯後

<li>0:1</li>
<li>1:2</li>
<li>2:3</li>
<li>3:4</li>複製程式碼
  • while
// 編譯前
- var arr = 4
while arr > 0
  li= arr--


// 編譯後

<li>4</li>
<li>3</li>
<li>2</li>
<li>1</li>複製程式碼
Mixins

Mixins允許您建立可重用的Pug block。

// 編譯前
mixin lists
 p this is a mixin block
+lists
+lists  

// 編譯後

<p>this is a mixin block</p>
<p>this is a mixin block</p>複製程式碼

mixins可以為一個帶引數的函式

// 編譯前
mixin link(href,name)
  a(href=href)= name

+link('www.baidu.com','百度')  

// 編譯後

<a href="www.baidu.com">百度</a>複製程式碼

mixins也可以使用一個block來作為內容

// 編譯前
mixin lists(names)
 p= 'my name is ' + names
 if block
   block
 else
   p not provided content
+lists('kobe')
+lists('cpul')
  p block content

// 編譯後

<p>my name is kobe</p>
<p>not provided content</p>
<p>my name is cpul</p>
<p>block content</p>複製程式碼

未知數量引數(...)的mixins.

// 編譯前
mixin lists(className,...items)
  ul(class=className)
    each item in items
      li= item

+lists('demo',1,2,3)
// 編譯後

<ul class="demo">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>複製程式碼
Tags

預設情況下,一行開頭的文字(或僅在空格之後)代表一個html標籤。 縮排的標籤是巢狀的,建立了像html的樹結構。

Pug可以判斷出哪些元素是自閉,您還可以通過簡單地附加'/'字元來明確地自己關閉標籤:

為了節省空間,Pug提供巢狀標記的內聯語法。

// 編譯前
p: span 內聯

// 編譯後
<p><span>內聯</span></p>複製程式碼

Pug的缺點

凡事不可能完美.Pug也有自己的弊端.

  • 可移植性差
  • 對新手除錯不方便
  • 效能不是很好

相關文章