玩转jade

前言

接触过一些不同种类的前端模版引擎 Mustache ejs mustache coffeecup…,大体上这些引擎都有相似的语法和功能,本质上都是通过弥补html与生俱来的缺陷,比如在模版种使用变量,循环,条件判断等加快应用的开发,本文要介绍的jade与上述模版引擎有些许不同,他是采用缩进的形式来组织html的。

声明

这篇文章默认你已经知道用”-“开头可以声明js变量与使用js语句,使用#{name}获取name变量的值, 文本在标签后空一个空格。

1. 标签

jade中默认一行中的第一个单词就是标签名称,如果不写标签名则默认创建一个div

1
2
3
4
5
.tag#tag
ul.list
li item1
li item2
li item3

编译后

1
2
3
4
5
6
7
<div id="wrap" class="wrap">
<ul class="list">
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>

2. 属性

一般我们需要在标签上面挂载一些属性,jade中标签的属性放在()中,多个属性之间使用,逗号隔开

2.1 基本用法

1
2
a(href="google.com") google.com
a(class="button", href="google.com") google.com

编译后

1
2
<a href="google.com">google.com</a>
<a href="google.com" class="button">google.com</a>

2.2 模版中夹杂js语句

当然了绝大多的js语句是可以模版中运行的

1
2
- var test = true; // 这里的test只要 弱为真即可( 注意前面的-符号 )
a(href=test ? 'google.com': 'baidu.com') js语句

编译后

1
<a href="google.com">js语句</a>

2.2 多个属性

想象一下,当你要给标签上面挂载多个属性的时候,全部写在一行必然不是什么好玩的事情,于是我们可以像下面这样写

1
2
3
4
5
input(
type="checkbox",
name= "qianlong",
checked
)

编译后

1
<input type="checkbox" name="qianlong" checked />

2.3 boolean类型属性

>

1
2
3
4
input(type="checkbox", checked )
input(type="checkbox", checked=true )
input(type="checkbox", checked=false )
input(type="checkbox", checked=true && 'checked' )

编译后

1
2
3
4
<input type="checkbox" checked>
<input type="checkbox" checked>
<input type="checkbox">
<input type="checkbox" checked="checked">

2.4 style 书写行间样式

当我们要在行间给一个元素单独的设置一段样式的时候,应该怎么做呢?直接给style属性赋值一段js对象即可

1
2
- styles = {color: 'red', background: 'green'}
a(href="google.com", style=styles) google.com

编译后

1
<a href="google.com" style="color:red;background:green">google.com</a>

2.5 单独添加class属性

前面在tag章节我们讲过可以通过.className的形式添加class,这里我们也可以把类当成是某个属性来书写,并且可以把一个数组直接赋值给class属性,亦可以是个对象类型的条件判断赋值

1
2
3
4
5
6
7
8
- var classes = ['qianlong', 'tianxiang', 'doubi'];
- var objTest = false;
a(class=classes, href="google.com") google.com
// 这里结合.className的形式
a.firstName.qianlong(class=classes, class="firstName", href="google.com") google.com
// 对象形式
a(class={'active': objTest}, href="google.com") google.com

编译后

1
2
3
<a href="google.com" class="qianlong tianxiang doubi">google.com</a>
<a href="google.com" class="firstName qianlong qianlong tianxiang doubi firstName">google.com</a>
<a href="google.com" class="active">google.com</a>

1. 可以看出当我们同时使用.className和属性书写的形式并且两者有相同的类名的时候,jade并不会非常智能地给我们只留下一下一个类,而是重复相同的类名多次

2. 我们可以利用使用对象类型添加class的方式来给不同的元素添加不同的类

3. 循环each && 条件判断 if

在模版引擎中除了使用变量动态的获取我们需要的数据,很多时候我们做的事是根据数据循环生成dom元素以及根据条件判断来涮选数据,很幸运jade给我们提供了这样的机制

3.1 each || for

我们可以通过each和js中的for语句来根据数据循环生成dom结构

1
2
3
4
5
6
7
8
- var list = ['qianlong', 'tianxiang', 'doubi'];
ul.list1
each val, index in list
li 值是:#{val} 索引是: #{index}
ul.list2
- for(var i = 0, len = list.length; i < len; i++)
li 值是:#{list[i]} 索引是: #{i}

编译后

1
2
3
4
5
6
7
8
9
10
<ul class="list1">
<li>值是:qianlong 索引是: 0 </li>
<li>值是:tianxiang 索引是: 1 </li>
<li>值是:doubi 索引是: 2 </li>
</ul>
<ul class="list2">
<li>值是:qianlong 索引是: 0 </li>
<li>值是:tianxiang 索引是: 1 </li>
<li>值是:doubi 索引是: 2 </li>
</ul>

可见两种方式都可以达到相同的遍历效果,但是后者代码量较大稍显繁琐,推荐使用第一种方式

3.2 if

通过if关键字来进行条件判断

1
2
3
4
5
6
7
- var ifTest = 0;
if ifTest > 10
p ifTest 大于10
else if ifTest == 10
p ifTest 等于10
else
p ifTest 小于10

编译后

1
<p>ifTest 小于10 </p>

4. case vs switch

在jade模版里面我们通过case、when和default关键字可以实现类似于编程语句中switch的效果

1
2
3
4
5
6
7
8
- var friends = 10;
case friends
when 0
p you have no friends
when 1
p you have a friends
default
p you have #{friends} friends

编译后

1
<p>you have 10 friends</p>

可见当when中没有与之相匹配的项时,会走默认的default,接下来我们来看一下这几种情形

1
2
3
4
5
6
7
- var friends = 0;
case friends
when 0
when 1
p you have a friends
default
p you have #{friends} friends

编译后

1
<p>you have a friends</p>

1
2
3
4
5
6
7
8
- var friends = 1;
case friends
when 0
p you have no friends
when 1
p you have a friends
default
p you have #{friends} friends

编译后

1
<p>you have a friends</p>

5. extends

在构建应用的过程中,我们可能需要扩展自己,以弥补自己的不足。这时候便可以能用到extends

layout.jade

1
2
3
4
5
6
doctype html
html
head
block title
body
block content

main.jade

1
2
3
4
5
6
extends ./layout.jade
block title
title 我是main title
block content
.content 我是main中的content部分

最终main.jade编译后dom结构是

1
2
3
4
5
6
7
8
<html>
<head>
<title>我是main title</title>
</head>
<body>
<div class="content">我是main中的content部分 </div>
</body>
</html>

这里就好像是在layout.jade中先埋好title和content这两个坑,然后在main.jade中把这两个坑给填上了,并且也继承了layout.jade的dom结构

6. include

一张网页的很多模块是公用的比如头部和尾部,我们可以将这些可以复用的部分作为单独的模块,然后被他页面的嵌入,在jade要实现这种效果用的是include关键字

head.jade

1
2
3
head
title 我是head部分
link(rel="stylesheet", type="text/css", href="../styles/index.css")

footer.jade

1
#footer 我是footer部分

index.jade

1
2
3
4
5
6
doctype html
html
include ./header.jade
body
#main 我是主题部分
include ./footer.jade

编译后

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<title>我是head部分</title>
<link rel="stylesheet" type="text/css" href="../styles/index.css">
</head>
<body>
<div id="main">我是主题部分</div>
<div id="footer">我是footer部分</div>
</body>
</html>

怎么样,是不是有当前使用jsp include的那种感觉,别着急include的强大之处并不仅仅是引进.jade类型的文件,他还可以引进类似.css``.js等的文件

index.css

1
2
3
body{
background-color: green;
}

index.jade

1
2
3
4
5
6
7
8
doctype html
html
head
title include test
style
include ../public/styles/index.css
body
#main 我是主题部分

编译后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title>include test</title>
<style>
body{
background-color: green;
}
</style>
</head>
<body>
<div id="main">我是主题部分</div>
</body>
</html>

结语

jade还有其他相关的语法,日常工作中需要我们常用的结合上述所说灵活使用

参考资料
jade官网