之前在建站:Node+MongoDb+Express简单实例一文中使用过express
,本文就来介绍下express
的jade
模板引擎,为什么不介绍另一个express
默认的模板引擎ejs
了,因为我觉得jade
更简洁,更符合我个人的喜好
注:jade
因为版权问题已改名为pug
了,具体可看这Renaming jade -> pug
安装执行
全局安装:
1
| sudo npm install -g jade
|
接下来我们先看下jade
命令的常用参数,,注意区分大小写
我们接着新建一个index.jade
文件,代码如下所示很简单:
1 2 3 4 5 6
| doctype html head title hello body h1 hello world
|
接着在命令行执行jade index.jade
,编译后的文件index.html
内容如下:
1
| <!DOCTYPE html><html><head><title>hello</title></head><body><h1>hello world</h1></body></html>
|
可以发现默认编译后的源码是被压缩过的,没有缩进不利于阅读,我们可以加上-P
参数后就发现源码是经过被美化过的了
1 2 3 4 5 6 7 8 9 10 11
| jade -P index.jade <!DOCTYPE html> <html> <head> <title>hello</title> </head> <body> <h1>hello world</h1> </body> </html>
|
不过每次修改后都需要到终端重新编译,有点过于麻烦,我们可以加上-w
参数实时监听文件变化保存后自动重新编译
标签
在html
代码里标签基本都是成对存在的,包裹在尖括号里面,而在jade
模板引擎里,不需要使用尖括号而且也不用成对存在,标签与标签之间的嵌套关系通过换行何缩进实现,比如以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| doctype html head title hello world body h1 hello span world h1 test //编译执行后结果: <!DOCTYPE html> <html> <head> <title>hello world</title> </head> <body> <h1>hello<span>world</span></h1> <h1>test</h1> </body> </html>
|
属性和文本
属性写在标签名后的括号内,多个属性用逗号分隔,css类名
以及id名
还可以直接通过与写css
代码相同的形式紧贴在标签名后面,如果标签名未写,默认为div
标签
标签名后第一个空格后面的内容会被编译成标签内的文本内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| doctype html head title hello world body a(id="aId" class="aClass" href="https://www.luckyw.cn",target="_blank") luckyw #divId.divClass hello world //编译执行后结果: <!DOCTYPE html> <html> <head> <title>hello world</title> </head> <body> <a id="aId" href="https://www.luckyw.cn" target="_blank" class="aClass">luckyw</a> <div id="divId" class="divClass">hello world</div> </body> </html>> </html>
|
多行文本
多行文本的实现有两种方式,第一种是在标签名后紧接写一个.
,这样后面的内容会被jade
模板视作文本域而保留换行符,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| p. 1a 2b 3c 4d //编译执行后结果: <p> 1a 2b 3c 4d </p>
|
注:由于是文本域,因此使用这种写法里面要嵌套标签时,只能写原生的html
标签了
1 2 3 4 5 6 7 8 9 10 11 12 13
| p. 1a<span>abcd</span> 2b 3c 4d //编译执行后结果: <p> 1a<span>abcd</span> 2b 3c 4d </p>
|
多行文本的第二种写法是在每行前加上|
,同时使用jade
语法嵌套标签,比如:
1 2 3 4 5 6 7 8 9 10 11 12
| p | 1a span abcd | 2b | 3c | 4d //编译执行后结果: <p>1a<span>abcd</span>2b 3c 4d </p>
|
多行文本的写法不仅可用于p
标签等,也常见于style
和script
标签,例如:
1 2 3 4
| script. console.log("hello"); console.log("world"); console.log("luckyw.cn");
|
注释
单行注释:
通过”//“实现,用双斜杠的注释会被输出到html
源码里
通过”//-“实现,不会被输出到html
源码里
1 2 3 4 5
| //我是一行注释,html源码可看到 //- 我是一行注释,不会输出到html源码里 //编译执行后结果: <!--我是一行注释,html源码可看到-->
|
变量
变量声明很简单,前面加上-
,之后使用js
语法定义变量,使用时变量通过#{变量名}
或者=变量名
就行了,比如:
1 2 3 4 5 6 7
| - var str = "hello world" p #{str} p=str //编译执行后结果: <p>hello world</p> <p>hello world</p>
|
注意:以#{变量名}
或者=变量名
方式输出的变量数据会进行html
转义,比如:
1 2 3 4 5 6 7
| - var js = "<script>alert(1)</script>" p #{js} p=js //编译执行后结果: <p><script>alert(1)</script></p> <p><script>alert(1)</script></p>
|
如果不想html
转义,可以将#
改成!
即可
1 2 3 4 5 6 7
| - var js = "<script>alert(1)</script>" p !{js} p!=js //编译执行后结果: <p><script>alert(1)</script></p> <p><script>alert(1)</script></p>
|
那如果就想输出#{}
和!{}
该怎么办呢?可以前面加\
来让Jade
引擎不编译变量
1 2 3 4 5 6 7
| - var js = "<script>alert(1)</script>" p \!{js} p \#{js} //编译执行后结果: <p>!{js}</p> <p>#{js}</p>
|
这两种写法#{变量名}
和=变量名
输出的区别如下:
1 2 3 4 5 6
| input(value="#{val}") input(value=val) //编译执行后结果: <input value="undefined"> <input>
|
可以看出用#{}
如果变量未定义,将会编译成undefined
作为值,但用=
来编译变量的话,如果变量未定义就忽略
有了变量就能轻松实现前后端分离,数据保存在JSON
文件里,前端用Jade
模板制作页面,在需要显示数据处用变量来实现,例如data.json
文件里:
1 2 3 4
| { "title":"hello world", "link":"https://luckyw.cn" }
|
index.jade
文件里:
1 2 3 4 5 6
| doctype html head title=title body a(href=link,target="_blank") luckyw
|
执行命令jade -P -w index.jade -O data.json
后Jade
文件里的变量被自动替换,编译出来的index.html
:
1 2 3 4 5 6 7
| <!DOCTYPE html> <html> <head> <title>hello world</title> </head> <body><a href="https://luckyw.cn" target="_blank">luckyw</a></body> </html>
|
流程控制
if else
:
1 2 3 4 5 6 7 8 9 10 11
| - var author="luckyw" if author p 作者:#{author} else p 无作者 if arr.length>0 p #{arr.join(", ")} //编译执行后结果: <p>作者:luckyw</p> <p>node, express, jade</p>
|
for in
:
1 2 3 4 5 6
| - for(var k in obj) p #{obj[k]} //编译执行后结果: <p>luckyw</p> <p>https://luckyw.cn</p>
|
each in
:
1 2 3 4 5 6 7
| - var obj = {"str":"luckyw","link":"https://luckyw.cn"} each v,k in obj p #{k}:#{v} //编译执行后结果: <p>str:luckyw</p> <p>link:https://luckyw.cn</p>
|
while
:
1 2 3 4 5 6 7 8 9 10 11 12
| - var a = 0 ul while a<4 li=a++ //编译执行后结果: <ul> <li>0</li> <li>1</li> <li>2</li> <li>3</li> </ul>
|
case when
:
1 2 3 4 5 6 7 8 9 10
| - var flag = 0 case flag when 1 p 对的 when 0: p 错误 default p 错误 //编译执行后结果: <p>错误</p>
|
mixin
之前在sass入门初体验中介绍过sass
中的mixin
,既能重用代码,而且维护简单,jade
也支持mixin
,可以理解为function
最简单的无参mixin
,下面声明了一个mixin
无参函数hello
,调用时函数名前加上+
:
1 2 3 4 5 6
| mixin hello p hello +hello //编译执行后结果: <p>hello</p>
|
带参数的mixin
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| mixin info(name,skills) p=name ul.skills each item in skills li=item +info("luckyw",["node","express","jade"]) //编译执行后结果: <p>luckyw</p> <ul class="skills"> <li>node</li> <li>express</li> <li>jade</li> </ul>
|
继承
jade
中使用block
和extend
实现模板的继承,block
块就是定义一段html
代码,hello
就是我们定义的block
块,定义好之后我们可以直接通过block hello
调用从而实现代码的复用
1 2 3 4 5 6 7
| block hello p luckyw.cn block hello //编译执行后结果: <p>luckyw</p> <p>luckyw</p>
|
但block
真正的作用在于占位,供子文件继承,例如每个文件的页头都一样,就body
里内容不一样,可以写一个header.jade
文件:
1 2 3 4 5 6
| doctype html head title header body block content
|
然后改写index.jade
,首先用extends
继承自header.jade
的,然后重写header.jade
里的block content
:
1 2 3 4
| extends header block content p this is content
|
编译执行后结果:
1 2 3 4 5 6 7 8 9
| <!DOCTYPE html> <html> <head> <title>header</title> </head> <body> <p>this is content</p> </body> </html>
|