pug模板引擎(下)

逻辑语法

以下是关于模板逻辑的语法。

JavaScript代码

不输出的代码

用 - 开始一段不直接进行输出的代码。

1
2
- for (var x = 0; x < 3; x++)
li item
1
2
3
<li>item</li>
<li>item</li>
<li>item</li>

输出的代码

用=开始一段带有输出的代码,它应该是可以被求值的一个JavaScript表达式。为安全起见,它将被HTML转义。

1
2
3
p
= '这个代码被 <转义> 了!'
p= '这个代码被 <转义> 了!'

1
2
3
4
5

<p>这个代码被 &lt;转义&gt; 了!
</p>
<p>这个代码被 &lt;转义&gt; 了!</p>
​`

不转义的输出代码

用 != 开始一段不转义的,带有输出的代码。这将不会做任何转义,所以用于执行用户的输入将会不安全。

1
2
3
p
!= '这段文字<strong>没有</strong>被转义!'
p!= '这段文字' + '<strong>没有</strong>被转义!'

1
2
<p>这段文字<strong>没有</strong>被转义!</p>
<p>这段文字<strong>没有</strong>被转义!</p>

变量

内容变量

使用=或#{}来进行变量的真实值替换。

1
2
3
4
5
6
7
- var title = "On Dogs: Man's Best Friend";
- var author = "enlore";
- var theGreat = "<span>转义!</span>";

h1= title
p #{author} 笔下源于真情的创作。
p 这是安全的:#{theGreat}
1
2
3
<h1>On Dogs: Man's Best Friend</h1>
<p>enlore 笔下源于真情的创作。</p>
<p>这是安全的:&lt;span&gt;转义!&lt;/span&gt;</p>

在 #{ 和 } 里面的代码也会被求值、转义,并最终嵌入到模板的渲染输出中。

1
2
- var msg = "not my inside voice";
p This is #{msg.toUpperCase()}

1
<p>This is NOT MY INSIDE VOICE</p>

Pug 足够聪明来分辨到底哪里才是嵌入表达式的结束,所以不用担心表达式中有 },也不需要额外的转义。

1
p 不要转义 #{'}'}!
1
2
<p>不要转义 }!</p>
​`

如果需要表示一个 #{ 文本,可以转义它,也可以用嵌入功能来生成。

1
2
p Escaping works with \#{interpolation}
p Interpolation works with #{'#{interpolation}'} too!

1
2
<p>Escaping works with #{interpolation}</p>
<p>Interpolation works with #{interpolation} too!</p>

使用!{}嵌入没有转义的文本进入模板中。

1
2
3
- var riskyBusiness = "<em>我希望通过外籍教师 Peter 找一位英语笔友。</em>";
.quote
p 张三:!{riskyBusiness}
1
2
3
<div class="quote">
<p>张三:<em>我希望通过外籍教师 Peter 找一位英语笔友。</em></p>
</div>

[注意]如果直接使用用户提供的数据,未进行转义的内容可能会带来安全风险。

属性变量

如果要在属性当中使用变量的话,需要进行如下操作。

1
2
3
4
5
- var url = 'pug-test.html';
a(href='/' + url) 链接
= '\n'
- url = 'https://example.com/'
a(href=url) 另一个链接
1
2
<a href="/pug-test.html">链接</a>
<a href="https://example.com/">另一个链接</a>

如果JavaScript运行时支持 ECMAScript 2015 模板字符串,还可以使用下列方式来简化属性值。

1
2
3
4
5
- var btnType = 'info'
- var btnSize = 'lg'
button(type='button' class='btn btn-' + btnType + ' btn-' + btnSize)
= '\n'
button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)

1
2
3
<button class="btn btn-info btn-lg" type="button"></button>

<button class="btn btn-info btn-lg" type="button"></button>

&attributes 语法可以将一个对象转化为一个元素的属性列表。

1
2
3
4
div#foo(data-bar="foo")&attributes({'data-foo': 'bar'})
- var attributes = {};
- attributes.class = 'baz';
div#foo(data-bar="foo")&attributes(attributes)
1
2
<div id="foo" data-bar="foo" data-foo="bar"></div>
<div class="baz" id="foo" data-bar="foo"></div>

变量来源

变量来源有三种,分别是pug文件内部、命令行参数和外部JSON文件。

  1. pug文件内部
    1
    2
    - var val = "测试内容"
    p= val
1
<p>测试内容</p>
  1. 命令行参数

使用–obj参数,就可以跟随一个对象形式的参数

1
>>> $ pug index.pug -w -P --obj '{val:"命令行数据"}

  1. 外部JSON文件

使用-O,跟随一个JSON文件的路径即可

1
>>> $ pug index.pug -w -P -O test.json

这三种方式,pug文件内部的变量优先级最多,而外部JSON文件和命令行传参优先级相同。

条件

pug 的条件判断的一般形式的括号是可选的,所以可以省略掉开头的 -,效果完全相同。类似一个常规的 JavaScript 语法形式。

if…else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- var user = { description: 'foo bar baz' }
- var authorised = false
#user
if user.description
h2.green 描述
p.description= user.description
else if authorised
h2.blue 描述
p.description.
用户没有添加描述。
不写点什么吗……
else
h2.red 描述
p.description 用户没有描述
1
2
3
4
<div id="user">
<h2 class="green">描述</h2>
<p class="description">foo bar baz</p>
</div>

pug 同样也提供了它的反义版本 unless.

1
2
3
4
5
- var user = { description: 'foo bar baz', name:'aaa' }
unless user.isAnonymous
p 您已经以 #{user.name} 的身份登录
if !user.isAnonymous
p 您已经以 #{user.name} 的身份登录
1
2
<p>您已经以 aaa 的身份登录</p>
<p>您已经以 aaa 的身份登录</p>

switch

case 是 JavaScript 的 switch 指令的缩写,并且它接受如下的形式.

1
2
3
4
5
6
7
8
- var friends = 10
case friends
when 0
p 您没有朋友
when 1
p 您有一个朋友
default
p 您有 #{friends} 个朋友
1
<p>您有 10 个朋友</p>

在某些情况下,如果不想输出任何东西的话,可以明确地加上一个原生的 break 语句。

1
2
3
4
5
6
7
8
- var friends = 0
case friends
when 0
- break
when 1
p 您的朋友很少
default
p 您有 #{friends} 个朋友

循环

pug 目前支持两种主要的迭代方式: each 和 while

each

这是 Pug 的首选迭代方式

1
2
3
ul
each val in [1, 2, 3, 4, 5]
li= val
1
2
3
4
5
6
7
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>

可以在迭代时获得索引值

1
2
3
ul
each val, index in ['〇', '一', '二']
li= index + ': ' + val
1
2
3
4
5
<ul>
<li>0: 〇</li>
<li>1: 一</li>
<li>2: 二</li>
</ul>

能够迭代对象中的键值

1
2
3
ul
each val, index in {1:'一',2:'二',3:'三'}
li= index + ': ' + val
1
2
3
4
5
<ul>
<li>1: 一</li>
<li>2: 二</li>
<li>3: 三</li>
</ul>

用于迭代的对象或数组仅仅是个 JavaScript 表达式,因此它可以是变量、函数调用的结果,又或者其他

1
2
3
4
- var values = [];
ul
each val in values.length ? values : ['没有内容']
li= val
1
2
3
<ul>
<li>没有内容</li>
</ul>

还能添加一个 else 块,这个语句块将会在数组与对象没有可供迭代的值时被执行

1
2
3
4
5
6
- var values = [];
ul
each val in values
li= val
else
li 没有内容
1
2
3
<ul>
<li>没有内容</li>
</ul>

[注意]也可以使用 for 作为 each 的别称

while

也可以使用 while 来创建一个循环

1
2
3
4
- var n = 0;
ul
while n < 4
li= n++
1
2
3
4
5
6
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>

混入

混入是一种允许在 Pug 中重复使用一整个代码块的方法

1
2
3
4
5
6
7
8
9
//- 定义
mixin list
ul
li foo
li bar
li baz
//- 使用
+list
+list
1
2
3
4
5
6
7
8
9
10
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>

混入可以被编译成函数形式,并传递一些参数

1
2
3
4
5
6
mixin pet(name)
li.pet= name
ul
+pet('猫')
+pet('狗')
+pet('猪')
1
2
3
4
5
<ul>
<li class="pet"></li>
<li class="pet"></li>
<li class="pet"></li>
</ul>

混入也可以把一整个代码块像内容一样传递进来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mixin article(title)
.article
.article-wrapper
h1= title
if block
block
else
p 没有提供任何内容。

+article('Hello world')

+article('Hello world')
p 这是我
p 随便写的文章
1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>没有提供任何内容。</p>
</div>
</div>
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>这是我</p>
<p>随便写的文章</p>
</div>
</div>

混入也可以隐式地,从“标签属性”得到一个参数 attributes

1
2
3
4
mixin link(href, name)
a(class!=attributes.class href=href)= name

+link('/foo', 'foo')(class="btn")

1
<a class="btn" href="/foo">foo</a>

也可以直接用 &attributes 方法来传递 attributes 参数

1
2
3
4
mixin link(href, name)
a(href=href)&attributes(attributes)= name

+link('/foo', 'foo')(class="btn")
1
<a class="btn" href="/foo">foo</a>

可以用剩余参数(rest arguments)语法来表示参数列表最后传入若干个长度不定的参数

1
2
3
4
5
6
mixin list(id, ...items)
ul(id=id)
each item in items
li= item

+list('my-list', 1, 2, 3, 4)
1
2
3
4
5
6
<ul id="my-list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>

文件包含

包含(include)功能允许把另外的文件内容插入进来

1
2
3
4
5
6
7
8
//- index.pug
doctype html
html
include includes/head.pug
body
h1 我的网站
p 欢迎来到我这简陋得不能再简陋的网站。
include includes/foot.pug

被包含的如果不是 pug 文件,那么就只会当作文本内容来引入

文件继承

pug 支持使用 block 和 extends 关键字进行模板的继承。一个称之为“块”(block)的代码块,可以被子模板覆盖、替换。这个过程是递归的。pug 的块可以提供一份默认内容,当然这是可选的。

1
2
3
4
5
6
7
8
9
10
11
12
//- layout.pug
html
head
   meta(charset="UTF-8")
title 我的站点 - #{title}
block scripts
script(src='/jquery.js')
body
block content
block foot
#footer
p 一些页脚的内容

现在来扩展这个布局:只需要简单地创建一个新文件,并如下所示用一句 extends 来指出这个被继承的模板的路径。现在可以定义若干个新的块来覆盖父模板里对应的“父块”。值得注意的是,因为这里的 foot 块 没有 被重定义,所以会依然输出“一些页脚的内容”

1
2
//- pet.pug
p= petName
1
2
3
4
5
6
7
8
9
10
11
12
13
//- page.pug
- var title = '宠物'
doctype html
html
head
meta(charset='UTF-8')
title 我的站点 - #{title}
block scripts
script(src='/jquery.js')
body
block content
block foot
p 一些页脚的内容
1
2
3
4
5
6
7
8
9
10
11
12
//- page-a.pug
extends layout.pug

block scripts
script(src='/jquery.js')
script(src='/pets.js')

block content
h1= title
- var pets = ['猫', '狗']
each petName in pets
include pet.pug
1
>>> $ pug pug-test -w -P    //pug-test是存放文件夹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- pug-a.html 文件-->

<!DOCTYPE html >
<html>
<head>
<meta charset="UTF-8"/>
<title>我的站点 - 宠物</title>
<script src="/jquery.js"></script>
<script src="/pets.js"></script>
</head>
<body>
<h1>宠物</h1>
<p></p>
<p></p>
<p>一些页脚的内容</p>
</body>
</html>

同样,也可以覆盖一个块并在其中提供一些新的块。如下所示,content 块现在暴露出两个新的块 sidebar 和 primary 用来被扩展。当然,它的子模板也可以把整个 content 给覆盖掉。

1
2
3
4
5
6
7
8
9
10
//- sub-layout.pug
extends page.pug

block content
.sidebar
block sidebar
p 什么都没有
.primary
block primary
p 什么都没有
1
2
3
4
5
6
7
8
9
10
//- page-b.pug
extends sub-layout.pug

block content
.sidebar
block sidebar
p 什么都没有
.primary
block primary
p 什么都没有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- page-b.html 文件 -->

<!DOCTYPE html >
<html>
<head>
<meta charset="UTF-8"/>
<title>我的站点 - 宠物</title>
<script src="/jquery.js"></script>
</head>
<body>
<div class="sidebar">
<p>什么都没有</p>
</div>
<div class="primary">
<p>什么都没有</p>
</div>
<p>一些页脚的内容</p>
</body>
</html>

扩展

pug 允许去替换(默认的行为)、prepend(向头部添加内容),或者 append(向尾部添加内容)一个块。 假设有一份默认的脚本要放在 head 块中,而且希望将它应用到 每一个页面,可以进行如下操作。

1
2
3
4
5
6
7
8
//- layout.pug
html
head
block head
script(src='/vendor/jquery.js')
script(src='/vendor/caustic.js')
body
block content

现在假设有一个页面,那是一个 JavaScript 编写的游戏。希望把一些游戏相关的脚本也像默认的那些脚本一样放进去,那么只要简单地 append 这个块:

1
2
3
4
5
6
7
8
//- page.pug
extends layout.pug

block prepend head
script(src='/vendor/three.js')

block append head
script(src='/game.js')

当使用 block append 或者 block prepend 时,block 关键字是可省略的:

1
2
3
4
5
6
7
8
//- page.pug
extends layout.pug

prepend head
script(src='/vendor/three.js')

append head
script(src='/game.js')

简易模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//- index.pug
doctype html
html
head
meta(charset="UTF-8")
title= documentTitle
each val in srcStyles
link(href= baseStyle +'/' + val)
body
header.hd
nav.hd-navbar.m-navbar.m-navbar_primary
.hd-navbar-tel 联系方式: #{tel}
ul.hd-navbar-nav
each val in mainNavItem
li.Hnn-item.m-btn.m-btn_info
a(href="#")= val

section.main
h1.main-title 我的文档
p.main-content.
这是一个很长很长而且还很无聊的段落,还没有结束,是的,非常非常地长。
突然出现了一个 #[strong 充满力量感的单词],这确实让人难以 #[em 忽视]。

footer.ft
p Copyright (c) 小火柴的蓝色理想

each val in srcScripts
script(src=baseScript + '/' + val)
1
2
3
4
5
6
7
8
9
10
//- data.json
{
"documentTitle":"测试文档",
"tel":"400-888-8888",
"mainNavItem":['登录','注册','关于','帮助'],
"baseStyle":'style',
"srcStyles":['bootstrap.css','main.css'],
"baseScript":'/js',
"srcScripts":['jquery.js','app.js']
}

评论

Ajax Android AndroidStudio Animation Anroid Studio AppBarLayout Banner Buffer Bulma ByteBuffer C++ C11 C89 C99 CDN CMYK COM1 COM2 CSS Camera Raw, 直方图 Chrome ContentProvider CoordinatorLayout C语言 DML DOM Dagger Dagger2 Darktable Demo Document DownloadManage Element Error Exception Extensions File FileProvider Fresco GCC Git GitHub GitLab Gradle Groovy HTML5 Handler HandlerThread Hexo Hybrid I/O IDEA IO ImageMagick IntelliJ Intellij Interpolator JCenter JNI JS Java JavaScript JsBridge Kotlin Lab Lambda Lifecycle Lint Linux Looper MQTT MVC MVP Maven MessageQueue Modbus Momentum MySQL NDK NIO NexT Next Nodejs ObjectAnimator Oracle VM Permission PhotoShop Physics Python RGB RS-232 RTU Remote-SSH Retrofit Runnable RxAndroid RxJava SE0 SSH Spring SpringBoot Statubar Task Theme Thread Tkinter UI UIKit UML VM virtualBox VS Code ValueAnimator ViewPropertyAnimator Web Web前端 Workbench api apk bookmark by关键字 compileOnly css c语言 databases demo hexo hotfix html iOS icarus implementation init jQuery javascript launchModel logo merge mvp offset photos pug query rxjava2 scss servlet shell svg tkinter tomcat transition unicode utf-8 vector virtual box vscode 七牛 下载 中介者模式 串口 临潼石榴 主题 书签 事件 享元模式 仓库 代理模式 位运算 依赖注入 修改,tables 光和色 内存 内核 内部分享 函数 函数式编程 分支 分析 创建 删除 动画 单例模式 压缩图片 发布 可空性 合并 同向性 后期 启动模式 命令 命令模式 响应式 响应式编程 图层 图床 图片压缩 图片处理 图片轮播 地球 域名 基础 增加 备忘录模式 外观模式 多线程 大爆炸 天气APP 太白山 头文件 奇点 字符串 字符集 存储引擎 宇宙 宏定义 实践 属性 属性动画 岐山擀面皮 岐山肉臊子 岐山香醋 工具 工厂模式 年终总结 开发技巧 异常 弱引用 恒星 打包 技巧 指针 插件 摄影 操作系统 攻略 故事 数据库 数据类型 数组 文件 新功能 旅行 旋转木马 时序图 时空 时间简史 曲线 杂谈 权限 枚举 架构 查询 标准库 标签选择器 样式 核心 框架 案例 桥接模式 检测工具 模块化 模板引擎 模板方法模式 油泼辣子 泛型 洛川苹果 浅色状态栏 源码 瀑布流 热修复 版本 版本控制 状态栏 状态模式 生活 留言板 相册 相对论 眉县猕猴桃 知识点 码云 磁盘 科学 笔记 策略模式 类图 系统,发行版, GNU 索引 组件 组合模式 结构 结构体 编码 网易云信 网格布局 网站广播 网站通知 网络 美化 联合 膨胀的宇宙 自定义 自定义View 自定义插件 蒙版 虚拟 虚拟机 补码 补齐 表单 表达式 装饰模式 西安 观察者模式 规范 视图 视频 解耦器模式 设计 设计原则 设计模式 访问者模式 语法 责任链模式 贪吃蛇 转换 软件工程 软引用 运算符 迭代子模式 适配器模式 选择器 通信 通道 配置 链表 锐化 错误 键盘 闭包 降噪 陕西地方特产 面向对象 项目优化 项目构建 黑洞
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×