首页 Pug 模板引擎速查
3.0.4 2026-03-13 pugjs/pug
打开 Zread CodeWiki
340px

快速定位

安装命令
最新版npm install pug
指定版本npm install pug@3.0.4
最新稳定版npm install pug@latest
CLInpm install pug-cli -g
CLI 帮助pug --help

基础标签

Pug 用缩进表示嵌套关系,不需要闭合标签。
doctype html
html(lang="zh-CN")
  head
    meta(charset="UTF-8")
    title 页面标题
  body
    h1 你好世界
    p 段落文本

常用 Doctype 变体

doctype html          // HTML5
doctype xml           // XHTML
doctype transitional   // HTML 4.01 Transitional
doctype strict         // HTML 4.01 Strict
doctype frameset       // HTML 4.01 Frameset

属性

属性写在圆括号 () 内,多个属性用逗号或空格分隔。
a(href='https://example.com', class='btn', target='_blank') 链接

input(
  type='text'
  name='username'
  placeholder='请输入用户名'
  disabled
)

button(type='submit', class='primary') 提交

ID 与 Class 简写

#header        // 生成 <div id="header">
.header        // 生成 <div class="header">
div#main.container   // 生成 <div id="main" class="container">
button#submit.btn.primary  // 生成 <button id="submit" class="btn primary">

文本与插值

// 行内插值
p 你好 #{name}!
p 当前计数:#{count}

// 属性插值
- var url = 'https://example.com'
a(href=url) 访问

// 纯文本行(前面加 |)
p
  | 第一行文本
  | 第二行文本

// 带格式文本块(前面加 .)
.article
  .content.
    这里的所有文本
    都会作为纯文本保留格式

注释

// 单行注释,输出到 HTML
//- 不输出的注释,不出现在编译结果中

// 块注释
//
  多行注释
  这些内容不会出现在 HTML 中

// 条件注释
<!--[if IE]>
<p>IE 专属内容</p>
<![endif]-->

内联代码

// 使用反单引号 `` 在标签后直接添加文本
p.
  这是内联代码块的第一行
  这是第二行

// 反单引号和点结合使用
span.
  内联文本内容

输出模式:Buffer vs 无缓冲

// = 表示输出,带转义
p= '你好 <b>世界</b>'   // 输出:&lt;b&gt;世界&lt;/b&gt;

// - 表示执行,不输出
- var html = '<b>粗体</b>'
p= html                    // 输出:<b>粗体</b>

// 不带 = 的文本
p 你好                    // 原样输出
p= '你好'                 // 同上,带转义

// 转义 vs 不转义
p!= '<b>粗体</b>'        // 不转义,输出 <b>粗体</b>
p= '<b>粗体</b>'         // 转义,输出 &lt;b&gt;粗体&lt;/b&gt;

循环

// each 循环
ul
  each item, index in ['苹果', '香蕉', '橙子']
    li #{index + 1}. #{item}

// 对象循环
ul
  each value, key in {name: '张三', age: 25, city: '北京'}
    li #{key}: #{value}

// for 循环
- for (var i = 0; i < 3; i++)
  p 第 #{i + 1} 项

// while 循环
- var n = 0
ul
  while n < 3
    li= n++

条件

// if/else
if user
  p 欢迎,#{user.name}
else
  p 请登录

// unless(相当于 if not)
unless isGuest
  p 会员专属内容

// case
case role
  when 'admin'
    p 管理员面板
  when 'user'
    p 用户面板
  default
    p 欢迎访问

Mixin

Mixin 用于代码复用,类似函数。
// 定义
mixin list(items)
  ul
    each item in items
      li= item

// 使用
+list(['苹果', '香蕉'])

mixin article(title, date)
  article
    h2= title
    time(datetime=date)= date

+article('标题文本', '2026-05-18')

// 带参数默认值
mixin button(text, type='primary')
  button(class='btn-' + type)= text

+button('取消', 'secondary')
+button('确认')

传入块内容

mixin modal(title)
  .modal
    .modal-header
      h3= title
    .modal-body
      block

+modal('提示')
  p 这里是对话框的内容

模板继承

block 与 extends

//- layout.pug(基础模板)
html
  head
    block title
      title 默认标题
  body
    block content
    block footer
      footer 默认页脚
//- index.pug(继承模板)
extends layout.pug

block title
  title 自定义标题

block content
  main
    h1 主页内容

block footer
  footer 自定义页脚

include

将其他文件内容引入当前模板。
// 引入头部
include _header.pug

// 引入页脚(带路径)
include ../partials/_footer.pug

// 引入片段
include ./_card.pug

&attributes

将对象展开为属性。
- var attrs = {class: 'btn', data-id: '123', disabled: true}
button&attributes(attrs) 点击

// 合并其他属性
button#main-btn.btn(data-action='submit')&attributes(attrs)

过滤器

过滤器在过滤器符号后缩进写内容,用于处理纯文本或特定语言。
// markdown 过滤器:渲染 markdown 为 HTML
:markdown
  # 标题
  - 列表项
  **粗体** 和 *斜体*

// plain 过滤器:原样输出,不解析 Pug 语法
:plain
  <div>这是纯文本,不会被解析为标签</div>
  #{name} 也会原样显示

// coffeescript 过滤器:编译 CoffeeScript
:coffee
  console.log 'Hello from CoffeeScript'
  squares = (x * x for x in [1..5])

自定义过滤器

// 在 API 中注册自定义过滤器
pug.renderFile('template.pug', {
  filters: {
    myFilter: function(text, options) {
      // 处理 text 并返回 HTML
      return '<div class="custom">' + text + '</div>';
    }
  }
});
:myFilter
  自定义过滤器内容

调试方法

// 1. 查看编译后的函数源码
pug.compile('p #{name}', {debug: true});
// 输出包含函数源码和 AST

// 2. 使用 basedir 定位错误文件
pug.renderFile('template.pug', {
  basedir: '/path/to/templates',
  filename: 'template.pug'
});

// 3. 捕获编译错误
try {
  const html = pug.renderFile('template.pug', {data: 'value'});
} catch (err) {
  console.error(err.message);
  console.error(err.filename);  // 出错文件
  console.error(err.line);     // 出错行号
}

// 4. pretty 输出便于调试
pug.renderFile('template.pug', {
  pretty: true,
  debug: true
});

// 5. 输出 AST 查看结构
const lex = require('pug-lexer');
const tokens = lex('p Hello');
console.log(tokens);

常用 API

const pug = require('pug');

// 渲染字符串
const html = pug.render('p 你好 #{name}', {name: '世界'});

// 渲染文件
pug.renderFile('template.pug', {data: 'value'}, (err, html) => {
  if (err) console.error(err);
  console.log(html);
});

// 编译模板函数
const fn = pug.compile('h1 #{title}');
console.log(fn({title: '标题'}));

// 编译文件
const compiled = pug.compileFile('template.pug');
console.log(compiled({name: '值'});

常用选项

选项说明默认值
pretty输出格式化 HTMLfalse
cache缓存编译结果false
basedir模板基础目录''
filename报错时显示的文件名undefined
debug输出调试信息false
globals全局变量白名单[]
self使用 self 命名空间存储局部变量false
pug.renderFile('template.pug', {
  pretty: true,   // 格式化输出
  cache: true,    // 生产环境开启
  basedir: '/views',
  globals: ['gloablVar1']  // 允许未声明的全局变量
});

CLI 常用命令

pug -P template.pug        # 格式化输出
pug -w template.pug        # 监听文件变化
pug -O data.json template.pug  # 从 JSON 加载数据
pug -o ./dist template.pug # 指定输出目录
pug --pretty template.pug  # 格式化输出
pug -V                     # 查看版本

易错点

// ❌ 常见错误:属性值不用引号包裹
a(href=https://example.com)  // 报错:应为 'https://example.com'

// ✅ 正确写法
a(href='https://example.com')

// ❌ 常见错误:混用 tab 和空格
doctype html
  head
→   title  // 缩进不一致会报错
    body

// ✅ 正确做法:保持一致的缩进风格(空格或 tab)

// ❌ 常见错误:变量未定义时插值显示 undefined
p 你好 #{undefinedVar}  // 显示 undefined

// ✅ 正确做法:确保变量已定义,或使用默认值
p 你好 #{user ? user.name : '游客'}

// ❌ 常见错误:= 和 != 混用导致 XSS
p!= userInput   // 可能存在 XSS 风险
p= userInput    // 安全,带转义

// ✅ 安全做法:确认来源后再决定是否转义

// ❌ 常见错误:include 路径错误
include _header.pug         // 可能找不到
include /partials/_header.pug  // 路径错误

// ✅ 正确做法:使用相对路径,基于 basedir 或当前文件位置

// ❌ 常见错误:block 和 include 混用
extends layout.pug
include _header.pug  // 在 extends 后不应再 include

// ✅ 正确做法:extends 只用于继承,include 用于引入片段

速查卡

语法说明
#idID 简写
.classClass 简写
(attr='val')属性
#{var}变量插值
= exprBuffer 输出(转义)
!= expr不转义输出
- code执行代码,不输出
//HTML 注释
//-不输出的注释
each val, key in obj循环
for i in rangefor 循环
while condwhile 循环
if/else条件
unless条件(非)
case/when多条件分支
mixin代码复用
+mixin()调用 mixin
include引入文件
extends继承模板
block模板块
&attributes(obj)属性展开
:filter过滤器
.文本块
``纯文本行