本系列的是参考慕课网 scott老师的视频,仅供个人查阅使用,具体讲解推荐参考视频。
同时也参考了Jade —— 源于 Node.js 的 HTML 模板引擎这篇文章的内容
Jade 已经更名为 Pug
安装 Pug:npm install -g pug
使用 Pug
如果要通过命令行使用 Pug,需要安装 pug-cli
1 | npm install -g pug-cli |
通过命令行使用 pug
1 | 使用: pug [options] [dir|file ...] |
API
1 | var pug = require('pug'); |
For full API, see jade-lang.com/api
Pug 基础语法
Pug 文档声明和头尾标签
使用 Pug 创建文档声明,可以使用 !!!
(不推荐),也可以使用 doctype
:
或
1 | !!! html |
当然也是可以直接传递一段文档类型的文本:
1 | doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" |
标签
标签就是一个简单的单词:
1 | html |
它会被转换为 <html></html>
标签也是可以有 id 的:
1 | div#container |
它会被转换为 <div id="container"></div>
怎么加 class 呢?
1 | div.user-details |
转换为 <div class="user-details"></div>
1 | div#foo.bar.baz |
转换为 <div id="foo" class="bar baz"></div>
如果有时候想在 .jade 文件中自行添加完整的 HTML 标签,Pug 也是可以顺利解析的。
1 | section |
标签文本
只需要简单的把内容放在标签之后:
1 | p wahoo! |
它会被渲染为 <p>wahoo!</p>
但是大段的文本怎么办呢:
1 | p |
渲染为 <p>foo bar baz rawr.....</p>
怎么和数据结合起来? 所有类型的文本展示都可以和数据结合起来,如果我们把 { name: ‘tj’, email: 'tj@vision-media.ca‘ } 传给编译函数,下面是模板上的写法:
1 | #user #{name} <#{email}> |
它会被渲染为 <div id="user">tj <tj@vision-media.ca></div>
要输出 #{}
的时候怎么办? 转义一下!
1 | p \#{something} |
同样可以使用非转义的变量 !{html}
, 下面的模板将直接输出一个 <script>
标签:
1 | - var html = "<script></script>" |
属性
Pug 现在支持使用 ( 和 ) 作为属性分隔符
1 | a(href='/login', title='View login page') Login |
当一个值是 undefined 或者 null 属性 不 会被加上,
所以呢,它不会编译出 ‘something=”null”‘.
1 | div(something=null) |
Boolean 属性也是支持的:
1 | input(type="checkbox", checked) |
假如我有一个 user 对象 { id: 12, name: 'tobi' }
我们希望创建一个指向 /user/12
的链接 href
, 我们可以使用普通的 JavaScript 字符串连接,如下:
1 | a(href='/user/' + user.id)= user.name |
注释
单行注释和 JavaScript 里是一样的,通过 //
来开始,并且必须单独一行:
1 | // just some paragraphs |
Pug 同样支持不输出的注释,加一个短横线就行了:
1 | //- will not output within markup |
渲染为:
1 | <p>foo</p> |
块注释
块注释也是支持的:
1 | body |
渲染为:
1 | <body> |
Pug 同样很好的支持了条件注释:
1 | body |
渲染为:
1 | <body> |
代码
变量声明和传递
可以在 .jade
文件中使用 - var course = jade
来定义变量,也可以在编译 .jade
文件的时候再指定变量。编译的时候指定变量的方法为:
1 | jade index.jade --obj {"course": "jade"} |
也可以先将变量写在一个 Json 文件里:
1 | // course.json |
-
Jade 目前支持三种类型的可执行代码。第一种是前缀 -
, 这是不会被输出的:
1 | - var foo = 'bar'; |
这可以用在条件语句或者循环中:
1 | - for (var key in obj) |
由于 Jade 的缓存技术,下面的代码也是可以的:
1 | - if (foo) |
甚至是很长的循环也是可以的:
1 | - if (items.length) |
=
下一步我们要 转义 输出的代码,比如我们返回一个值,只要前缀一个 =
:
1 | - var foo = 'bar' |
它会渲染为 bar<h1>bar</h1>
. 为了安全起见,使用 =
输出的代码默认是转义的,如果想直接输出不转义的值可以使用 !=
:
1 | p!= aVarContainingMoreHTML |
Jade 同样是设计师友好的,它可以使 JavaScript 更直接更富表现力。比如下面的赋值语句是相等的,同时表达式还是通常的 JavaScript:
1 | - var foo = 'foo ' + 'bar' |
Jade 会把 if, else if, else, until, while, unless 同别的优先对待, 但是你得记住它们还是普通的 JavaScript:
1 | - var foo = 'bar' |
输出是:
1 | <ul> |
循环
遍历数组或者对象的时候,使用 for
或者 each
,不可以在之前加上 -
。因为 for
和 each
是 pug 中的关键字,不是代表着 JavaScript 的代码
一个遍历数组的例子 :
1 | - var items = ["one", "two", "three"] |
遍历一个数组同时带上索引:
1 | items = ["one", "two", "three"] |
遍历一个数组的键值:
1 | obj = { foo: 'bar' } |
如果你喜欢,也可以使用 for :
1 | for user in users |
还可以使用 while
1 | - var n = 0 |
条件语句
1 | for user in users |
Jade 同时支持 unless, 这和 if (!(expr)) 是等价的:
1 | for user in users |
Mixins
一般是定义一个列表里面重复的区块
Mixins 在编译的模板里会被 Jade 转换为普通的 JavaScript 函数。 Mixins 可以带参数
1 | mixin list |
Mixins 也可以带一个或者多个参数,参数就是普通的 JavaScript 表达式,比如下面的例子:
1 | mixin pets(pets) |
或者传入不定个数的参数
1 | mixin pets(pets, ...item) |
使用 +
调用 mixin
1 | +pets(pets) |
会输出像下面的 HTML:
1 | <ul class="pets"> |
mixin 中也可以嵌套调用 mixin,使用 +
就可以调用。
Pug 进级
模板继承
Jade 支持通过 block
和 extends
关键字来实现模板继承。 一个块就是一个 Jade 的 block ,它将在子模板中实现,同时是支持递归的。
Jade 块如果没有内容,Jade 会添加默认内容,下面的代码默认会输出 block scripts
, block content
, 和 block foot
.
1 | html |
1 | extends extend-layout |
注意,子模板的 block 会覆盖父模板中同名的 block
前置、追加代码块
使用 append
来为 block 添加额外的部分
Jade允许你 替换 (默认)、 前置 和 追加 blocks. 比如,假设你希望在 所有 页面的头部都加上默认的脚本,你可以这么做:
1 | html |
现在假设你有一个Javascript游戏的页面,你希望在默认的脚本之外添加一些游戏相关的脚本,你可以直接append上代码块:
1 | extends layout |
包含
一般使用继承 extend
的时候,还需要为其中的 block
定义。但是使用 include
的时候,就人为 include
进来的文件是一个完整的文件,不需要为其中的 block
定义
include
允许你静态包含一段 Jade, 或者别的存放在单个文件中的东西比如 CSS, HTML 非常常见的例子是包含头部和页脚。 假设我们有一个下面目录结构的文件夹:
1 | ./layout.jade |
下面是 layout.jade
的内容:
1 | html |
这两个包含 includes/head
和 includes/foot
都会读取相对于给 layout.jade
参数 filename
的路径的文件, 这是一个绝对路径
前面已经提到,include 可以包含比如 HTML 或者 CSS 这样的内容。给定一个扩展名后,Jade 不会把这个文件当作一个 Jade 源代码,并且会把它当作一个普通文本包含进来:
1 | include head.html |
过滤器
在过滤器里面不能传递动态的数据!
可以通过插件添加生成 HTML 的功能,常用的有 :babel, :uglify-js, :scss, :markdown-it
反编译
可以使用 html2jade
模块将 HTML 文件转换为 Jade 文件