Jade简单教程
Express框架里内嵌了Jade模板引擎。正好项目里也要用到,本篇整理了下Jade的相关用法。
- 安装与执行
- 标签和属性
- 多行文本
- 变量
- 语句
- Mixin
- 模板
- 注释
- 过滤器
安装与执行
安装很简单:
npm install jade –global
安装后本地随便新建一个sample.jade文件,执行:
jade sample.jade
就能将其翻译成标准的sample.html源文件了。执行时可以带上参数,通过jade -h查看支持的命令参数:
常用的命令参数,比如-P(大写,命令参数是大小写敏感的)。Jade默认编译出来的html源文件里是没有缩进的,不便于开发。加上-P参数后,编译出来的html源文件里就有缩进了:
jade -P sample.jade
还有-w用来watch监视jade文件,每次改动保存后自动编译成html文件,省去手动执行命令的麻烦:
jade -P -w sample.jade
-O用来给jade文件传递对象或JSON文件,用以替换模板内的变量:
jade -P -w sample.jade -O sample.json
标签和属性
传统的HTML标签写尖括号很麻烦,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是最常用的标签属性,所以Jade简化了它俩的写法,可以紧接在标签名后面。但标签属性的正统写法应该是写入()括号内,多个属性用逗号隔开(css类名和id也可以写入()括号内):
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
- unless
- case-when
- for-in
- each-in
- while
最常见的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无参函数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去进行处理。
作者:张歆琳
链接:http://www.jianshu.com/p/e2a9cd3b7e56
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Jade简单教程的更多相关文章
- Git和Github简单教程
原文链接:Git和Github简单教程 网络上关于Git和GitHub的教程不少,但是这些教程有的命令太少不够用,有的命令太多,使得初期学习的时候需要额外花不少时间在一些当前用不到的命令上. 这篇文章 ...
- FusionCharts简单教程(三)-----如何自定义图表上的工具提示
最近有蛮多人总是问我这个FusionCharts制表的问题,帮助他们解决之后,在昨晚发现以前整理的笔记中有这个简单教程,而且以前也发表了几篇这个博文,所以就将其全部上传上来供别人参考.如有不正确之处望 ...
- FusionCharts简单教程(八)-----使用网格组件
有时候我们会觉得使用图像不够直接,对于数据的显示没有表格那样直接明了.所以这里就介绍如何使用网格组件.将网格与图像结合起来.网格组件能够将FusionCharts中的单序列数据以列表的 ...
- Qt Quick 简单教程
上一篇<Qt Quick 之 Hello World 图文详解>我们已经分别在电脑和 Android 手机上运行了第一个 Qt Quick 示例—— HelloQtQuickApp ,这篇 ...
- Git和Github简单教程(收藏)
原文链接:Git和Github简单教程 目录: 零.Git是什么 一.Git的主要功能:版本控制 二.概览 三.Git for Windows软件安装 四.本地Git的使用 五.Github与Git的 ...
- mysql安装简单教程(自动安装/配置安装)
mysql安装简单教程(自动安装/配置安装) 1.1前言: 由于特殊原因,在最近2-3个月里mysql真是安装了无数遍,每次安装都要上网找教程,每个教程基本都不一样,因此还是自己写下来比较好,毕竟自己 ...
- 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)
原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...
- LayaAir引擎开发HTML5最简单教程(面向JS开发者)
LayaAir引擎开发HTML5最简单教程(面向JS开发者) 一.总结 一句话总结:开发游戏还是得用游戏引擎来开发,其实很简单啦 切记:开发游戏还是得用游戏引擎来开发,其实很简单,引擎很多东西都帮你做 ...
- mockito简单教程
注:本文来源:sdyy321的<mockito简单教程> 官网: http://mockito.org API文档:http://docs.mockito.googlecode.com/h ...
随机推荐
- Word2003文档窗口分成上下两个独立的窗口
http://www.officezu.com/word/2003/index16.html 拆分窗口就是把一个Word2003文档窗口分成上下两个独立的窗口,从而可以通过两个Word2003文档窗口 ...
- linux C 内存分配(~道的光芒四射~)
总结一下C语言中基本的内存分配,加深对内存管理的印象,一步一步走山路~~~~~~~~ 1. 程序和进程 问题:程序和进程各是什么? 程序 只是一段可以执行的代码文件,通俗讲在 linux 上就是一个 ...
- Android 自定义圆形旋转进度条,仿微博头像加载效果
微博 App 的用户头像有一个圆形旋转进度条的加载效果,看上去效果非常不错,如图所示: 据说 Instagram 也采用了这种效果.最近抽空研究了一下,最后实现的效果是这样: 基本上能模拟出个大概,代 ...
- 阿里、华为、腾讯Java技术面试题精选
阿里.华为.腾讯Java技术面试题精选 2017-10-27 19:30技术/腾讯/华为 JVM的类加载机制是什么?有哪些实现方式? 类加载机制: 类的加载指的是将类的.class文件中的二进制数据读 ...
- pandas 操作 excel
1. 多重 sheet Using Pandas to pd.read_excel() for multiple worksheets of the same workbook pd.read_exc ...
- Eclipse之NDK编译-- Type 'jint' could not be resolved, and JNIEnv, jclass错误解决办法
最近在研究面部识别美白相关的功能.使用的是opencv,就去研究了.今天正好有空就把安装了ndk,安装完成之后就试图去编译demo程序,hellow-jni c代码,一开始编辑就报错了3个错误信息: ...
- with() {} 的用法
var use = "other"; var katana = { isSharp: true, use: function(){ this.isSharp = !!this.is ...
- HPU 1166: 阶乘问题(一)
1166: 阶乘问题(一) [数学] 时间限制: 1 Sec 内存限制: 128 MB提交: 58 解决: 24 统计 题目描述 小H对阶乘!很感兴趣.现在他想知道N!N!的位数,由于NN太大了,所以 ...
- CTF-练习平台-Misc之 图片又隐写
八.图片又隐写 修改后缀名为zip,打开解压出两个文件 解压发现有密码,用WinHex打开发现文件头是zip的,所以出来把后缀名改为zip,再用工具爆破 最后得到解压密码,解压后是一个图片,改后缀名为 ...
- LeetCode-Microsoft-Remove K Digits
Given a non-negative integer num represented as a string, remove k digits from the number so that th ...