之前做小项目用的一直是ejs模板,今天开始做的这个项目需要用到jade模板,来学习一下
标签和属性
jade中可以省略尖括号,直接写标签名,标签间的嵌套关系用换行加空格实现。紧接在标签名后加上.xx或#xx,就能给标签添加css类名和id。标签名后第一个空格后面的内容会被编译成标签内的文本内容。例如:
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也可以写入()括号内):
a(href='hhtp://www.xiaohuahua.net',target='_blank')我的主页
//编译结果
<a href='hhtp://www.xiaohuahua.net',target='_blank'>我的主页</a>
对于经常使用的标签div,jade提供了一种简化的写法,如果不写标签名默认就是div
.divClass#divID我是一个div
//编译结果
<div id="divID" class="divClass">我是一个div</div>
变量
变量声明很简单,前面加上-横杠。使用变量只要#{变量名}就行了。例如:
- 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作为初始值。但用=等号来编译变量的话,如果变量未定义就忽略。
语句
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
Mixin不是新概念,例如sass里也用Mixin封装css代码,即能重用代码,而且维护简单。Jade也支持Mixin,可以理解为function,最简单的无参数的代码函数:
mixin sayHi
p Hi
+sayHi
//编译出来的结果
<p>Hi</p>
带参数示例:
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>
//编译出来的结果
<p>Jack's hobbies:</p>
<ul class="hobby">
<li>movie</li>
<li>music</li>
</ul>
模板
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>
//编译出来的结果
<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
注释
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个空格。