pug模块

pug 模块,原名 jade,因版权问题,更名为 pug,中文意思为 “哈巴狗”,它也是 Web 开发中常用的一种模板引擎。使用 pug 模块之前,首先需要使用 npm 命令进行下载和安装,命令如下:

npm install pug

下面介绍如何在 Node.js 中使用 pug 模块。

pug文件基础语法

要使用 pug 模板引擎,必然需要用到 pug 文件,pug 文件不同于 html 文件和 ejs 文件,它不需要标签的开和闭,比如 html 中的 <p>Demo</p>,在 pug 中使用 p Demo 即可,因此本节首先带领大家熟悉一下 pug 文件的基本语法。

缩进

pug 对空格敏感,这类似于 Python 对制表符(Tab)或者空格敏感的特点。pug 使用空格作为缩进符,同一级标签需保证左对齐。例如:

div
     p Hello, world!
     p Hello, pug.

上面代码的渲染结果如下:

<div>
     <p>Hellow, world!</p>
     <p>Hello, pug.</p>
</div>

注释

pug 使用 //- 或 // 对代码进行注释,前者注释内容不出现在渲染后的 html 文件中,后者反之。例如:

//- html中不包含此行
// html中会包含此行

属性

pug 将标签属性存放于括号 () 内,多个属性之间以逗号或空格分隔。另外,对于标签的 idclass 属性,pug 分别使用 “#紧跟标签id” 和 “.紧跟标签 class” 形式表示,而且可以同时设置多个 class。例如:

h1#title Test title
img#name.class1.class2(src="/test.png" alt="test")

上面代码的渲染结果如下:

<h1 id="title">Test title</h1>
<img id="name" class="class1 class2" src="/test.png" alt="test">

包含

为了方便代码复用,pug 提供了 include 包含功能。例如,下面代码会将 _partial 目录下的 head.pug 文件内容包含到当前调用的位置:

doctype html
html(lang='en')
     include _partial/head.pug

定义变量

pug 中通过 “- var name = value” 的形式定义变量,例如:

- var intData = 100
- var boolData = false
- var stringData = 'Test'

在引用变量时,需要在引用位置加上 = 号,否则会默认将变量名当成普通字符串使用。例如:

p.int= intData
p.bool= boolData
p.stringData= stringData

如果想要将变量与其他字符串常量或变量连接在一起,需要使用 #{},该符号会对大括号内的变量进行求值和转义,最终得到输出的内容。例如:

- var girl = 'Lily'
- var boy = 'Jack'
p #{girl} is so beautiful!
p And #{boy} is handsome.

条件结构

pug 的条件语句与其他语言的条件语句类似,形式如下:

- var A = {value: 'Test'}
- var B = true
if A.value
     p= A.value
else if B
     p= B
else
     p nothing

循环结构

pug 中使用 eachwhile 实现循环结构。其中,each 可以返回当前所在项的索引值,默认从 0 开始计数。例如:

ol
     each item in ['Sun', 'Mon', 'Tus', 'Wen', 'Thu', 'Fri', 'Sat']
          li= item
- var week = ['Sun', 'Mon', 'Tus', 'Wen', 'Thu', 'Fri', 'Sat']
ol
     each item, index in week
          li= index + ':' + item

上面代码的渲染结果如下:

<ol>
     <li>Sun</li>
     <li>Mon</li>
     <li>Tus</li>
     <li>Wen</li>
     <li>Thu</li>
     <li>Fri</li>
     <li>Sat</li>
</ol>
<ol>
     <li>0:Sun</li>
     <li>1:Mon</li>
     <li>2:Tus</li>
     <li>3:Wen</li>
     <li>4:Thu</li>
     <li>5:Fri</li>
     <li>6:Sat</li>
</ol>

while 使用方式如下:

- var day = 1
ul
while day < 7
     li= day++

minix

mixin 被称为混入,类似其他编程语言中的函数,也是为了代码复用,可带参数或不带参数,定义方式如下:

mixin menu-item(href, name)
     li
          span.dot ●
          a(href=href)= name

其中,menu-item 为调用时的名称,相当于函数名;hrefname 是参数。这里需要注意,a(href=href)= name 中第二个 = 是为了将后面的 name 当作参数来处理,而不是当作字符串 “name” 来处理。

要调用 mixin 定义的代码块,需通过 “+号紧跟 mixin 名称及参数” 的形式,例如:

+menu-item('/Archives','Archives')
+menu-item('/About','About')

mixin 之所以被称为混入,是因为其语法不局限于函数调用,在 mixin 内也可以使用 block 块,例如:

mixin print(post)
     if block
          block
     else
          p= post
+print("no block")
+print("")
     div.box
          p this is the content of block

上面代码的渲染结果如下:

<p>no block</p>
<div class="box"><p>this is the content of block</p></div>

定义JavaScript代码

pug 中编写 JavaScript 代码时,需要使用以下形式:

script(type='text/javascript').
     var data = "Test"
     var enable = true
     if enable
          console.log(data)
     else
          console.log('nothing')

注意上面代码中第一行最后的 “.” 符号。

上面代码对应的 JavaScript 代码如下:

<script type='text/javascript'>
     var data = "Test"
     var enable = true
     if enable
          console.log(data)
     else
          console.log('nothing')
</script>

这里需要说明的是,对于简单脚本,使用 pug 尚可,而如果遇到复杂的 JavaScript 脚本,建议写在单独的 .js 文件中,然后通过 pug 引用,引用方式如下:

script(type='text/javascript', src='/path/to/js')

继承

pug 支持继承,通过继承,也可以提高代码的复用率。例如,下面代码是一个简单的 base 模板,其中通过 block 定义了页面头部 head 和内容 body

//- base.pug
html
     head
          block title
     body
          block content

接下来就可以使用 extends 继承上面的模板,通过 block 覆盖或替换原有块 block,代码如下:

//- index.pug
extends base.pug
block title
     title "Test title"
block content
     h1 Hello world!
     block article

jade 文件与 pug 文件 “师出同门”,其语法与 pug 文件一致,因此,如果遇到 jade 文件中的代码,可以参考上面语法进行解读。

pug模块的渲染方法

使用 pug 模块之前,首先需要进行导入,代码如下:

var pug = require('pug');

pug 模块提供了多个方法,用于渲染数据或 pug 文件,下面分别介绍。

compile()方法

compile() 方法用来把一个 pug 模板编译成一个可多次使用并能传入不同局部变量进行渲染的函数。语法格式如下:

pug.compile(string,options)
  • string:要编译的 pug 模板。

  • options:可选参数,指定一些用于解析模板的参数。

  • 返回值:一个根据本地配置生成的 HTML 字符串。

compileFile()方法

compileFile() 方法用于从文件中读取一个 pug 模板文件,并编译成一个可多次使用并能传入不同局部变量进行渲染的函数。语法格式如下:

pug.compileFile(path, options)
  • path:要编译的 pug 文件路径。

  • options:可选参数,配置渲染数据的相关参数。

  • 返回值:一个根据本地配置生成的 HTML 字符串。

compileClient()方法

compileClient() 方法用于将一个 pug 模板编译成一份 JavaScript 代码字符串,以便在客户端调用,生成 HTML。语法格式如下:

pug.compileClient(source, options)
  • source:要编译的 pug 模板。

  • options:可选参数,用于配置编译数据的相关参数。

  • 返回值:一份 JavaScript 代码字符串。

compileClientWithDependenciesTracked()方法

该方法与 compileClient() 方法类似,但是其返回值为 DOM 对象,该方法适用于监视 pug 文件更改之类的操作。

compileFileClient()方法

compileFileClient() 方法从文件中读取 pug 模板并编译成一份 JavaScript 代码字符串,它可以直接用在浏览器上而不需要 pug 的运行时库。语法格式如下:

pug.compileFileClient(path, options)
  • path:要编译的 pug 文件路径。

  • options:可选参数,用于配置编译数据的相关参数,如果 options 中指定了 name 属性,那么它将作为客户端模板函数的名称。

  • 返回值:一份 JavaScript 代码字符串。

render()方法

render() 方法用于渲染 pug 代码中的数据,并生成 HTML 代码,语法格式如下:

pug.render(source, options, callback)
  • source:需要渲染的 pug 代码。

  • options:存放可选参数的对象,同时也直接用作局部变量的对象。

  • callbackNode.js 风格的回调函数(注意:这个回调是同步执行的),用于接收渲染结果。

  • 返回值:渲染出来的 HTML 字符串。

renderFile()方法

renderFile() 方法用于渲染 pug 文件中的数据,并生成 HTML 代码,语法格式如下:

pug.renderFile(path, options, callback)
  • pathstring 需要渲染的 pug 代码文件的位置。

  • options:存放选项的对象,同时也直接用作局部变量的对象。

  • callbackNode.js 风格的回调函数(注意:这个回调是同步执行的),用于接收渲染结果。

  • 返回值:渲染出来的 HTML 字符串。

下面通过实例演示 pug 模块的基本使用。

【例13.4】模拟获取消费券页面。(实例位置:资源包\源码\13\04)

步骤如下。

(1) 在 WebStorm 中创建一个 .js 文件,该文件的主要作用是创建服务器,以及从客户端获取数据并且使用 pug 模板引擎进行渲染。代码如下:

//引入模块
var http = require('http');
var pug = require('pug');
var fs = require('fs');
//创建服务器
http.createServer(function (request, response) {
     //读取pug文件
     fs.readFile('index.pug', 'utf8', function (error, data) {
          //调用pug模块的compile方法解析pug模板代码
          var fn = pug.compile(data);
          response.writeHead(200, { 'Content-Type': 'text/html' });
          response.end(fn());
     });
}).listen(52273, function () {
     console.log('服务器监听地址是 http://127.0.0.1:52273');
});

(2) 创建 index.pug 文件,该文件中主要使用 pug 语法设置页面中要显示的数据,代码如下:

doctype html
html
     head
          meta(charset="UTF-8")
          title 微信支付
     body
          div(style={margin:'0 auto',width:'300px','line-height':'80px','border':'1px dashed #8bc34a'})
               h3(style={'text-align':'center','line-height':'40px','margin':'0px 0px'}) 恭喜你获得指定商家消费券
               p(style={'text-align':'center','color':'red','line-height':'40px','margin':'0px 0px'}) ¥3.66元
               div(style={'text-align':'center','line-height':'40px'}) 已存入卡包,下次消费自动抵扣
               div(style={'text-align':'center','line-height':'40px','font-size':'12px'}) 微众银行助力智慧生活

运行 .js 文件,在浏览器中输入 http://127.0.0.1:52273/ ,可以看到浏览器中的界面效果如图13.5所示。

image 2024 04 17 15 10 53 378
Figure 1. 图13.5 获取消费券

pug模块的数据传递

本节将讲解动态向 pug 模板中传递数据的方法。要动态向 pug 模板传递数据,需要在服务器端输出渲染的数据时,通过自定义属性存储要传递给客户端的数据,然后在 pug 文件中使用 #{} 绑定服务器端自定义的相应属性。

【例13.5】月度消费账单提醒。(实例位置:资源包\源码\13\05)

步骤如下。

(1) 在 WebStorm 中创建一个 .js 文件,该文件中使用 pub 模块的 compile() 方法解析 pug 模板代码并显示,在显示时,将自定义的 monthoutin1 等属性返回给客户端。代码如下:

//引入模块
var http = require('http');
var pug = require('pug');
var fs = require('fs');
//创建服务器
http.createServer(function (request, response) {
     //读取pug文件
     fs.readFile('index.pug', 'utf8', function (error, data) {
          //调用pug模块的compile方法解析pug模板代码
          var fn = pug.compile(data);
          response.writeHead(200, { 'Content-Type': 'text/html' });
          //向客户端返回信息
          response.end(fn({
               month: '2023年6月',
               out:"520.10",
               in1:3370.34,
               transport:"120.00",
               shopping:"300.00",
               medical:87.10,
               other: "13.00"
          }));
     });
}).listen(52273, function () {
     console.log('服务器监听地址是 http://127.0.0.1:52273');
});

(2) 创建一个 index.pug 文件。在文件中,通过使用 pug 渲染标识,将服务器返回给客户端的自定义属性显示到指定的 HTML 标签中。代码如下:

doctype html
html
     head
          meta(charset="UTF-8")
          title 手机账单提醒
     body
          div(style={margin:'0 auto',width:'300px',border:'solid blue 1px','padding':'20px'})
               h3(style={'text-align':'center','margin-bottom':'0'}) 月度账单提醒
               p(style={'text-align':'center','font-size':'12px','margin':'4px auto 10px'}) 月份: #{month}
               p(style={'text-align':'center','font-size':'20px','margin':'0 auto','color':'#009688'}) 支出: #{out}
               p(style={'text-align':'center','font-size':'12px','margin-top':'0'}) 收入: #{in1}
               p
                     span 明细:
                     span(style={'color':'#009688','background':'rgba(156, 223, 244, 0.5)',
                          'border-radius':'5px','float':'right','font-size':'12px','padding':'5px 10px','margin-right':'5px'}) 支出
                     span(style={'color':'#2d2525','background':'rgba(170, 170, 170, 0.33)',
                          'border-radius':'5px','float':'right','font-size':'12px','padding':'5px 10px','margin-right':'5px'}) 收入
               p
                     span 交通:
                     span(style={'float':'right'}) ¥ #{transport}
               p
                     span 购物:
                     span(style={'float':'right'}) ¥ #{shopping}
               p
                     span 医疗:
                     span(style={'float':'right'}) ¥#{medical}
               p
                     span 其他:
                     span(style={'float':'right'}) ¥#{other}

运行 .js 文件,在浏览器中输入 http://127.0.0.1:52273/ ,可以看到浏览器中的界面效果如图 13.6 所示。

image 2024 04 17 15 14 12 701
Figure 2. 图13.6 月度消费账单提醒