Express框架裏內嵌了Jade模板引擎。正好項目裏也要用到,本篇整理了下Jade的相關用法。css
安裝很簡單:html
npm install jade –global
安裝後本地隨便新建一個sample.jade文件,執行:前端
jade sample.jade
就能將其翻譯成標準的sample.html源文件了。執行時能夠帶上參數,經過jade -h查看支持的命令參數:jquery
經常使用的命令參數,好比-P(大寫,命令參數是大小寫敏感的)。Jade默認編譯出來的html源文件裏是沒有縮進的,不便於開發。加上-P參數後,編譯出來的html源文件裏就有縮進了:npm
jade -P sample.jade
還有-w用來watch監視jade文件,每次改動保存後自動編譯成html文件,省去手動執行命令的麻煩:json
jade -P -w sample.jade
-O用來給jade文件傳遞對象或JSON文件,用以替換模板內的變量:後端
jade -P -w sample.jade -O sample.json
傳統的HTML標籤寫尖括號很麻煩,Jade裏能夠省略尖括號,直接寫標籤名。標籤間的嵌套關係用換行加空格來實現。緊接在標籤名後加上.xx或#xx,就能給標籤添加css類名和id。標籤名後第一個空格後面的內容會被編譯成標籤內的文本內容。例如:sass
doctype html html head body h1.titleClass#titleID My First Jade Page //編譯出來的結果 <!DOCTYPE html> <html> <head></head> <body> <h1 id="titleID" class="titleClass">My First Jade Page</h1> </body> </html>
是否是感受寫起來簡單多了。由於css類名和id是最經常使用的標籤屬性,因此Jade簡化了它倆的寫法,能夠緊接在標籤名後面。但標籤屬性的正統寫法應該是寫入()括號內,多個屬性用逗號隔開(css類名和id也能夠寫入()括號內):markdown
a(href='http://www.jackzxl.net', target='_blank') 個人主頁 //編譯出來的結果 <a href="http://www.jackzxl.net" target="_blank">個人主頁</a>
HTML裏最經常使用的標籤就是div了,因此Jade提供了第二種簡化寫法,若是不寫標籤名默認就是div:框架
.divClass#divID 我是一個div //編譯出來的結果 <div id="divID" class="divClass">我是一個div</div>
單行文本像上面這樣接在標籤名後的空格後面便可。多行文本有兩種寫法。第一種寫法是在標籤名後緊接一個.點。這樣後面的內容會被Jade模板視做文本域而保留換行符。例如:
p. 第1行文本 第2行文本 第3行文本 第4行文本 //編譯出來的結果 <p> 第1行文本 第2行文本 第3行文本 第4行文本 </p>
但因爲是文本域,所以用這種寫法的話,裏面要嵌套標籤時,只能寫原生的HTML標籤了:
p. 第1行文本 第2行文本 第3行文本 第4行文本 //編譯出來的結果 <p> <span>第1行文本</span> 第2行文本 第3行文本 第4行文本 </p>
多行文本的第二種寫法是在每行前加上|豎線符。並且若是開發者以爲第一種寫法裏寫原生HTML標籤不爽,用這種寫法,能夠用Jade語法來嵌套標籤。例如:
p span 第1行文本 | 第2行文本 | 第3行文本 | 第4行文本 //編譯出來的結果 <p><span>第1行文本</span>第2行文本 第3行文本 第4行文本 <p>
多行文本的寫法不只可用於p標籤等,也常見於style和script標籤,例如:
script. console.log("open mind"); console.log("learning quick"); console.log("work hard");
若是僅僅上面這些快速編寫HTML的功能,那Jade也不必存在了。各類編輯器都有插件能夠實現這種快速編寫的功能,例如sublime的Emmet插件。模板引擎的真正強大之處能夠實現函數式的開發。先看變量。
變量聲明很簡單,前面加上-橫槓。使用變量只要#{變量名}就好了。例如:
- var cs = 'UTF-8' meta(charset='#{cs}') //編譯出來的結果 <meta charset="UTF-8">
但注意用#{}輸出的變量數據會執行HTML轉碼,例如:
- var alertData = '<script>alert(1);</script>' p #{alertData} //編譯出來的結果 <p><script>alert(1);</script></p>
本來想被執行的script腳本,被直接做爲文本打印出來了。若是不想HTML轉碼,能夠將#改爲!歎號:
- var alertData = '<script>alert(1);</script>' p !{alertData} //編譯出來的結果 <p><script>alert(1);</script></p>
那若是頁面就想輸出#{}和!{}呢?能夠前面加\反斜槓來讓Jade引擎不編譯變量:
p \#{alertData} p \!{alertData} //編譯出來的結果 <p>#{alertData}</p> <p>!{alertData}</p>
除了用#{}和!{}外,也能夠在標籤後面緊接=等號(不轉義用!=)來輸出變量。例如:
p= alertData p!= alertData
效果和上面是同樣的。這兩種寫法#{}和=等號輸出的區別以下:
input(value='#{aaa}') input(value=aaa) //編譯出來的結果 <input value="undefined"> <input>
能夠看出用#{}若是變量未定義,將會編譯成undefined做爲初始值。但用=等號來編譯變量的話,若是變量未定義就忽略。
有了變量就能輕鬆實現先後端分離。數據保存在JSON文件裏。前端用Jade模板製做頁面,在須要顯示數據處用變量來實現。例如sample.json文件裏:
{ "charset": "UTF-8", "title": "My First Jade Page" }
sample.jade文件裏:
doctype html html head meta(charset='#{charset}') body h1.titleClass#titleID #{title}
執行命令:jade -P -w sample.jade -O sample.json
後Jade文件裏的變量被自動替換。編譯出來的sample.html:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <h1 id="titleID" class="titleClass">My First Jade Page</h1> </body> </html>
Jade模板支持JavaScript語句:
最多見的if-else:
- var author = 'Jack'; if author p 做者:#{author} else p 無做者 //編譯出來的結果 <p>做者:Jack</p>
Jade還支持unless語句,它是if-else的反向,寫法都同樣,用的很少就不舉例了。
Jade裏的case-when語句就是JavaScript裏的switch-case語句(不知爲什麼…):
- var authors = ['Jack', 'Bill']; case authors[0] when 'Jack' p 做者是Jack when 'Bill' p 做者是Bill default p 無做者 //編譯出來的結果 <p>做者是Jack</p>
循環遍歷用for-in(注意上面的if-else,case-when語句前不用像變量那樣加上-橫槓,但for的前面要加上-橫槓。若是漏寫-橫槓,會被解析爲標籤):
- var person = {name:'Jack', gender: 'Male'} - for (var prop in person) p= person[prop] //編譯出來的結果 <p>Jack</p> <p>Male</p>
循環遍歷也能夠用each-in(each前的-橫槓加不加都可):
- var employee = {name:'Jack', gender: 'male'} - each value, key in person p #{key}: #{value} - var language = ['Java', 'JavaScript', 'C++'] ul each item in language li #{item} //編譯出來的結果 <p>name: Jack</p> <p>gender: male</p> <ul> <li>Java</li> <li>JavaScript</li> <li>C++</li> </ul>
循環遍歷也能夠用while(一樣前面加不加-橫槓都可):
- var n = 0 ul while n < 4 li= n++ //編譯出來的結果 <ul> <li>0</li> <li>1</li> <li>2</li> <li>3</li> </ul>
Mixin也不是個什麼新的概念,例如sass裏也用Mixin封裝css代碼,即能重用代碼,並且維護簡單。Jade也支持Mixin,能夠理解爲function,最簡單的無參數的代碼函數:
mixin sayHi p Hi +sayHi //編譯出來的結果 <p>Hi</p>
上面聲明瞭一個mixin無參函數sayHi,調用時函數名前加上+加號。如今給mixin加上參數:
mixin personInfo(name, hobbies) p #{name}'s hobbies: ul.hobby each hobby in hobbies li= hobby +personInfo('Jack', ['movie', 'music']) //編譯出來的結果 <p>Jack's hobbies:</p> <ul class="hobby"> <li>movie</li> <li>music</li> </ul>
函數內天然也可調用其餘函數,例如上面兩個函數嵌套起來。這些和普通JavaScript的函數表現一致,沒啥好多介紹的:
mixin personInfo(name, hobbies) +sayHi p #{name}'s hobbies: ul.hobby each hobby in hobbies li= hobby +personInfo('Jack', ['movie', 'music'])
mixin能夠實現代碼的複用。文件與文件間經常使用模板來實現代碼複用。Jade用block和extends來實現模板的繼承。block塊就是定義一段HTML模塊:
block scripts script(src='jquery.js') script(src='underscore.js') script(src='backbone.js') //編譯出來的結果 <script src="jquery.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script>
上面的塊名就是scripts。定義好的block後,本文件內能夠直接用block scripts來調用,這和mixin做用差很少,都能實現代碼複用。但block真正的做用在於佔位,供子文件繼承,能夠理解爲傳統OO語言裏的虛函數。父文件裏定義的block,子文件裏用extends來繼承並重寫。
例如每一個文件的頁頭都同樣,就body裏內容不同,能夠寫一個header.jade:
doctype html html head meta(charset='#{charset}') block scripts script(src='jquery.js') script(src='underscore.js') script(src='backbone.js') body block content p please write content
每一個頁面的header都長這樣。而body裏定義了block content,這裏block能夠理解爲一個佔位符placeholder,須要繼承它的文件重寫block content。
根據業務需求寫頁面主體部分,例如sample.jade改爲這樣:
extends header block content h1.titleClass#titleID #{title} a(href='http://www.jackzxl.net', target='_blank') 個人主頁 ……
在sample.jade裏,開頭用extends代表和header.jade的繼承關係。而後根據業務重寫header.jade裏的block content。
執行jade -P -w sample.jade -O sample.json
就能看到和以前如出一轍的頁面。引擎加載流程是:解析sample.jade,發現開頭有extends,就去解析header.jade,將其編譯成html。此時html裏的body裏是<p>please write content</p>
。解析完header.jade就繼續解析sample.jade,發現block content,因而會將定義在header.jade裏的block content替換掉。最終輸出的是正確的頁面內容,而不是<p>please write content</p>
。
(但若是你執行的是jade -P -w header.jade -O sample.json
會發現body裏內容爲<p>please write content</p>
)
除繼承外還能夠用include包含。Include會將內容無腦全拷貝進去。例如上面的sample.jade第一行extends header改爲include header。編譯出來的結果:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="jquery.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script> </head> <body> <p>please write content</p> </body> </html> <h1 id="titleID" class="titleClass">My First Jade Page</h1> <a href="http://www.jackzxl.net" target="_blank">個人主頁</a>
能夠看出與extends不一樣,include就是無腦將另外一個文件裏的內容直接拷貝進去,不像block + extends能夠重寫block。因此結果是錯誤的。
小細節注意:include包括extends若是省略後綴名,Jade默認該文件時.jade會進行編譯。但若是另外一個文件裏寫的是原生的html,須要寫明後綴名爲.html(例如include xx.html),明確告訴Jade不要編譯。
Jade里加上//就能添加註釋,用雙斜槓的註釋會被輸出到html源碼裏。例如:
//一行無心義的註釋 //編譯出來的結果 <!--一行無心義的註釋-->
若是不想在html源碼裏輸出註釋,用//-,在雙斜槓後加一橫槓。例如:
//-一行無心義的註釋,編譯時直接跳過該行,不會被輸出到HTML源碼裏
咱們知道html裏還能夠寫註釋型的條件語句,經常使用於兼容IE。Jade裏你一樣能夠寫這些條件語句,例如將上面header.jade改爲能識別IE89,應用不一樣的class:
doctype html <!--[if IE 8]><html class='ie8'><![endif]--> <!--[if IE 9]><html class='ie9'><![endif]--> <!--[if !IE]><!--><html><!--<![endif]--> head meta(charset='#{charset}') block scripts script(src='jquery.js') script(src='underscore.js') script(src='backbone.js') body block content p please write content </html>
上面由於有了條件語句,因此html標籤用尖括號括了起來,所以最下面要手動加上來閉合標籤。並且Jade是空格縮進敏感的,須要將原先的head和body包括裏面內容,全往前縮進2個空格。
Jade一樣兼容其餘模塊,例如寫博客愛用的markdown,寫css愛用的less,還有coffeeScript等。只要npm安裝好後,用:冒號+模塊名就能聲明使用這些模塊,例如:
:markdown ... :less ... :coffee ...
以:markdown 爲例,會把下面塊裏的文本交給markdown去進行處理。