Pug,原名 Jade, 是一个很流行的 HTML 模板引擎,后来由于 Jade 被注册为商标的原因,改名为 Pug,中文官网在这里。
npm install pug -g
如果需要使用命令行对 pug 模板进行编译,还需要安装 pug-cli
npm install pug-cli -g
Pug 和原来用过的 Smarty 模板、Ractive 模板类似,都是通过一个函数(Pug中是 pug.compile()
)将模板便以为 JavaScript 函数,函数中通过{}
传入变量。最终编译结果就是 HTML 代码。
创建一个 hello.pug
div
p Hello Pug
在命令行输入:
pug hello.pug -w
就会编译出 hello.html
<div>
<p>Hello Pugp>
<div>
其中 -w
选项为监听模式,自动相应模板的改动并且实时编译
使用 pug --help
查看命令行帮助
看一些基本的用法:
# 编译 templates 文件夹下所有模板
$ pug templates
# 编译 foo 文件夹下和 bar 文件夹下的模板至 tmp 文件夹(绝对路径)
$ pug foo bar --out /tmp
# 编译 foo.pug 并美化 html 代码
$ pug foo.pug -P
关键点就是找到 pug.cmd
文件的全局位置:
C:\Users\xxxxx\AppData\Roaming\npm\pug.cmd
其中 xxxx
是用户名
这样在 pug 模板的同级目录下, websotrm就会自动编译一份 HTML
这样的缺点是代码的格式还需要手动调整,并且 pug 文件改变,HTML 格式又自动变回去了
在 Arguments 增加 -P
参数也同样可以美化代码
html2jade 这个网站可以在线将 HTML 代码转换为 jade 代码
pug 模板中省略了 HTML 中的标签<>
,并且使用缩进代表包含关系,标签后空格内容表示标签中内容
doctype html
head
meta(charset='utf-8')
title Hello Pug
body
div
p Hello Pug
编译结果
<head>
<meta charset="utf-8">
<title>Hello Pugtitle>
head>
<body>
<div>
<p>Hello Pugp>
div>
body>
Pug知道那个元素自闭合的,当然如果想要手动添加,可以直接在标签后紧接一个 /
来声明此标签是自闭合的
label
input(type="text")/
:
是一种省略写法,目的仅仅是节省空间
label: input(type="text")/
HTML 标签中的属性用 ()
包围起来,属性之间用 ,
隔开,属性值用 ‘’
包裹
a(href='//www.baidu.com', title='百度一下') 百度一下
编译后:
<a href="//www.baidu.com" title="百度一下">百度一下a>
上面提到了,利用空格分割表示文本,多行文本需要在标签后加 .
, 文本内容保持同样缩进
如果文本中还包含标签,则需要直接添加标签
p.
line1
line2
line3 <strong>strongstrong>
编译后
<p>
line1
line2
line3 <strong>strongstrong>
p>
这种情况一般适用于大段文字的例子,比如 中的内容:
script.
(function test() {
alert(123)
})()
编译后
<script>
(function test() {
alert(123)
})()
script>
也可以使用 |
来书写,效果相同
p
| line1
| line2
| line3 strong
如果一行的开头是尖括号 <
,那么正行都会当做纯文本,即便当中的内容包含 HTML 标签,也会原样输出:
<span>123span>
单行注释:
// 这个注释会被编译到HTML
//- 这个注释不会被编译到HTML
块注释
//
块注释
块注释
IE注释
利用 -
开始一段不直接进行输入的代码
- for (var i = 0; i<3; i++)
p #{i}
利用 =
开始一段带有输出的代码(注意 =
前后不能有空格)
- for (var i = 0; i<3; i++)
p=i
编译后
<p>1p>
<p>2p>
<p>3p>
声明变量使用 -var varName = varValue
, 使用变量 #{varName}
- var text='Pug'
p Hello #{text}
编译后
<p>Hello Pugp>
默认情况下,所有属性都经转义,目的是为了防止跨站脚本攻击等攻击方式
- var unescaped = 'Hello'
p #{unescaped}
编译后
<p><strong>Hello</strong></p>
如果需要使用特殊字符,即未经过转义的字符, 在引用变量时使用 !{}
代替 #{}
(在定义属性时用 !=
代替 =
)
- var unescaped = 'Hello'
p !{unescaped}
编译后
<p><strong>Hellostrong>p>
未经定义的变量输出结果是空值,而非 undefined
class
可以是一个字符串,也可以是一个包含多个类名的数组
p(class=['class1', 'class2']) class
编译后
<p class="class1 class2">classp>
也可以是一个对象
p(class={class3: false, class4: true}) class
编译后
class="class4">class</p>
类可以使用 .classname
语法来定义, ID 使用 #idname
来定义,在省略标签名是默认是 div
//
p.class5 class
p#id1 id
.class6 class
编译后
class="class5">class
id="id1">id
<div class="class6">classdiv>
&attributes
&attributes
语法可以将一个对象转化为一个元素的属性列表。
p#id2(class='class7')&attributes({'data-url': '//www.baidu.com'})
编译后
<p class="class7" id="id2" data-url="//www.baidu.com">p>
可以省略语句开头的 -
, 类似常规的 JavaScript 语法形式
- var number = function() {return 15};
if(number() < 0)
p number < 0
else if(number() > 5)
p number > 5
else
p number between (0,5)
unless varA
等同于 if(!varA)
就按照字面意思理解,如果不,这样便于记忆
使用 each
实现循环是最常见的方式,第二个参数就是循环时的索引值
ul
each val in [1,2,3,4,5]
li #{val + 'index' + index} // 等同于 li=val + 'index' + index
编译后
<ul>
<li>1index0li>
<li>2index1li>
<li>3index2li>
<li>4index3li>
<li>5index4li>
ul>
也可以对对象进行循环
- var object = {name: 'chow', age:22};
ul
each value, key in object
li=key + ':' + value
编译后
<ul>
<li>name:chowli>
<li>age:22li>
ul>
用于迭代的对象或数组仅仅是个 JavaScript 表达式,因此它可以是变量、函数调用的结果
each value, key in friends > 110 ? object : ''
可以为 each
添加一个 else
块,用于当被循环对象无法提供被循环内容时调用
- var friends = 100
ul
each value, key in friends > 110 ? object : ''
li=key + ':' + value
else
li nothing
也可以使用 while
来创建循环
- var n = 0;
ul
while n < 4
li= n++
case
是 JavaScript 中 switch
中的缩写
- var friends = 1
case friends
when 1
p you only have 1 friend
when 2
p you have 2 friends
default
p you have a lot of friends
可以使用块展开的语法:
- var friends = 11
case friends
when 1: p you only have 1 friend
when 2: p you have 2 friends
default: p you have a lot of friends
相当于 JavaScript 中的 import
功能
// - index.pug
doctype html
html
include includes/head.pug
body
h1 我的网站
p 欢迎来到我这简陋得不能再简陋的网站。
include includes/foot.pug
// - includes/head.pug
head
title 我的网站
编译后:
<html>
<head>
<title>我的网站title>
<script src="/javascripts/jquery.js">script>
<script src="/javascripts/app.js">script>
head>
<body>
<h1>我的网站h1>
<p>欢迎来到我这简陋得不能再简陋的网站。p>
<footer id="footer">
<p>Copyright (c) foobarp>
footer>
body>
html>
被包含的如果不是 Pug 文件,那么就只会当作文本内容来引入。
script
include say.js
// say.js
alert('hello');
编译后:
<script>
alert('hello');
script>
Pug 支持使用 block
和 extends
实现继承,一个称之为“块”(block)的代码块,可以被子模板覆盖、替换。这个过程是递归的。
简单来说就是,b.pug 通过 extends a.pug
关键词来继承 a.pug 中的全部代码,再通过声明与 a.pug 中相同的 block
来替代原来模板中的内容
Pug 允许您去替换(默认的行为)、prepend
(向头部添加内容),或者 append
(向尾部添加内容)一个块。
Pug 模板继承是一个非常强大的功能,您可以借助它将复杂的页面模板拆分成若干个小而简洁的文件。然而,如果您将大量的模板继承、链接在一起,那么有可能会反而把事情弄得更加复杂。
Mixin 实现了代码的复用
mixin myMixin
li This should be repeated
编译后:
ul
each n in [1,2,3]
+myMixin
<ul>
<li>This should be repeatedli>
<li>This should be repeatedli>
<li>This should be repeatedli>
ul>
可以向 myMixin
中传入参数
mixin myMixin(text)
li This should be #{text}
编译后:
ul
each n in [1,2,3]
+myMixin(n)
<ul>
<li>This should be 1li>
<li>This should be 2li>
<li>This should be 3li>
ul>
其实可以将 Mixin 理解为一个函数,返回值是一段 HTML 代码,每次调用都会返回相同值
function myMixin(text){
return `This should be ${text} `
}
也可以通过 block
关键字将外部内容传入到 Mixin 中
mixin article(name)
if block
block
else
p 默认内容
+article
p ------------------
+article
p 随便写点什么
编译后:
<p>默认内容p>
<p>------------------p>
<p>随便写点什么p>
可以向 Mixin 中引入 rest
参数
mixin rest(name, ...others)
each other in others
p='剩余参数是' + other
+rest('old_chow', 1,2,3,4,5)
<p>剩余参数是1p>
<p>剩余参数是2p>
<p>剩余参数是3p>
<p>剩余参数是4p>
<p>剩余参数是5p>
当然是 arguments
对象在 Mixin 中也是可以使用的
arguments
是传入函数的所有参数,rest
是对应位置的参数
在 Vue 的单文件组件中的 中可以使用 Pug 进行模板的编写(JADE步骤相同)
首先安装 Pug 依赖
npm install pug pug-loader pug-filters -D
安装成功后,在 webpack 的配置文件 webpack.base.conf.js 的 modules
中的 rules
节点下添加如下配置:
{
test: /\.pug$/,
loader: 'pug'
}
这样,.vue
单文件组件 就支持 Pug 并实时编译了。
<template lang="pug">
ul
- var arr = [1,2,3]
each value in arr
li(id="test" + value) value + {{this.name}}
template>
<script>
export
default {
data() {
return {
name: 'chow'
}
},
computed: {},
methods: {},
components: {}
}
script>