express框架的渲染模板有多种选择,官方的例子是Pug,网上找了一下,Pug没有能够参考的中文文档,因而本身动手丰衣足食。翻译水平通常,各位凑合着看吧。javascript
安装css
经过npm安装pug:html
$ npm install pug
简介java
Pug的渲染语句很简单,pug.compile()方法将pug源文件(.pug)源文件编译成一个带参数(‘locals’,pug文件的路径)方法,而后调用这个结果方法就能购生成一段由pug文件转化成的html字符串。node
这个pug.compile()方法能够重复使用,生成各类各样的html字符串来渲染html。jquery
//- template.pug,pug文件 p #{name}'s Pug source code!
调用方法:web
const pug = require('pug'); // 编译pug源文件 const compiledFunction = pug.compileFile('template.pug'); // 渲染数据 console.log(compiledFunction({ name: 'Timothy' })); // "<p>Timothy's Pug source code!</p>" // 渲染另外一个数据 console.log(compiledFunction({ name: 'Forbes' })); // "<p>Forbes's Pug source code!</p>"
Pug还提供另一种渲染方式:pug.render系列的方法,它把编译和渲染合并成一个步骤,不须要生成编译函数,直接渲染pug源文件。固然,默认状况下调用它每次都要编译一次,这可能会影响性能。能够选择配置项cache为true,将编译函数缓存起来,不用每次都从新生成,编译。以下面的pug.renderFile方式:express
const pug = require('pug'); // Compile template.pug, and render a set of data console.log(pug.renderFile('template.pug', { name: 'Timothy' })); // "<p>Timothy's Pug source code!</p>"
Pug和Express结合,参考这个指南。npm
生产环境配置json
Express中环境变量NODE_ENV用来标识当前应用是在开发环境仍是生产环境。Express和Pug会根据这个环境变量自动修改一些配置选项,为用户提供友好的“开箱即用”的使用体验。
例如,在Express中使用Pug时,当process.env.NODE_ENV是“production”,compileDebug选项是false,默认状况下它是true。
能够经过设置app.locals或者res.locals为true或者false来覆盖compileDebug和cache的默认选项值。还能够经过Express的app.disable/enable('view cache')放来开修改cache选项。
更多细节,参考Express的api文档。
本节详细介绍Pug的api。
提示:能够直接在浏览器的console中访问这些api,例如:pub.render('p Hello world!')。
Pug中的方法参数以下:
filename:string
要编译的文件的路径和名字,使用相对路径,保留后缀,默认是'.pug'。
basedir:string
全部文件的入口目录。
doctype:string
若是没有在Pug模板中指定doctype,能够在这里指定。
pretty:boolean | string
[不建议]在渲染HTML结果中添加一些空白字符串做为空格,以便阅读。若是使用字符串,则将改字符串做为特定的空格使用(例如'\t'制表符)。不建议使用这个选项。因为这个选项修改空白的解析和渲染方式,一般会带来意想不到的后果,所以后续版本中这个选项将被取消。默认值为false。
filters:object
自定义hash table过滤器,默认未定义。
self:boolean
使用默认自定义空间的locals,加快编译速度,无需编写变量,只须指定self.variable获取locals。默认false。
debug:boolean
若是设置为true,tokens和函数体将输出到日志中。
compileDebug:boolean
若是设置为true,错误信息中将包含方法源码便于排查(测试环境会颇有用)。该选项默认开启,在正式环境关闭。
globals:Array<string>
在html模板中添加全局变量
cache:boolean
若是设置为true,将缓存编译函数。使用pug源文件的名字做为cache的键值。render类的函数有这个选项,默认是false。
inlineRuntimeFunctions:boolean
内联函数,代替require,在compileClient函数内,默认是true(没必要包含运行时)。在其余编译和渲染类型的函数中,这个选项默认是flase。
name:string
模板函数名。只在compileClient函数内。默认值是‘template’。
将一个Pug模板编译成一个函数,根据不一样参数能够被屡次渲染。
source:string
要编译的pug源文件。
options:?options
选项对象。
returns:function
返回值是一个根据本地配置生成html的函数。
var pug = require('pug'); // 生成编译函数 var fn = pug.compile('string of pug', options); // 调用编译函数渲染html var html = fn(locals); // => '<string>of pug</string>'
将一个pug源文件编译成一个方法,根据不一样参数能够屡次调用。
path:string
pug文件的路径
options:?options
选项对象
returns:function
返回值是一个根据本地配置生成html的函数。
var pug = require('pug'); // 生成编译函数 var fn = pug.compileFile('path to pug file', options); // 调用编译函数渲染html var html = fn(locals); // => '<string>of pug</string>'
将一个pug源文件编译成一段JavaScript函数字符串,能够用在客户端,调用这个函数返回html代码。
path:string
pug文件的路径
options:?options
选项对象
returns:function
返回值是一个JavaScript函数字符串
var pug = require('pug'); // 生成编译函数 var fn = pug.compileClient('string of pug', options); // 调用编译函数生成一个函数字符串,这个函数函数返回html代码 var html = fn(locals); // => 'function template(locals) { return "<string>of pug</string>"; }'
和compileClient方法相似,不一样之处在与这个函数返回一个dom结构对象。以下:
{ 'body': 'function (locals) {...}', 'dependencies': ['filename.pug'] }
仅当须要依赖来实现诸如监视Pug文件的更改之类的操做时,才应使用此方法。
编译一个Pug源文件便觉得可在客户端与pug运行时一块儿使用的JavaScript字符串。
path:string
pug文件的路径
options:?options
选项对象
options.name:string
若是在options选项中指定了name属性,它将做为客户端模板函数的名称
returns:function
返回值是一个JavaScript函数主体
假设下面是pug文件内容:
h1 This is a Pug template
h2 By #{author}
而后将pug文件编译为函数字符串。
var fs = require('fs'); var pug = require('pug'); // 将模板编译为函数字符串 var jsFunctionString = pug.compileFileClient('/path/to/pugFile.pug', {name: "fancyTemplateFun"}); // 能够将全部模板便觉得template.js文件提供给客户端 fs.writeFileSync("templates.js", jsFunctionString);
这是输出函数字符串的样子(写到templates.js)
function fancyTemplateFun(locals) { var buf = []; var pug_mixins = {}; var pug_interp; var locals_for_with = (locals || {}); (function (author) { buf.push("<h1>This is a Pug template</h1><h2>By " + (pug.escape((pug_interp = author) == null ? '' : pug_interp)) + "</h2>"); }.call(this, "author" in locals_for_with ? locals_for_with.author : typeof author !== "undefined" ? author : undefined) ); return buf.join(""); }
除了编译的模板以外,还要确保将Pug运行时(node_modules / pug / runtime.js)发送给客户端。以下:
<!DOCTYPE html> <html> <head> <script src="/runtime.js"></script> <script src="/templates.js"></script> </head> <body> <h1>This is one fancy template.</h1> <script type="text/javascript"> var html = window.fancyTemplateFun({author: "enlore"}); var div = document.createElement("div"); div.innerHTML = html; document.body.appendChild(div); </script> </body> </html>
source:string
要渲染的pug模板
options:?options
选项对象
callback: ?function
一个接受渲染结果回调函数,能够同步调用。
returns:function
返回值是一个JavaScript函数字符串
var pug = require('pug'); var html = pug.render('string of pug', options); // => '<string>of pug</string>'
path:string
pug文件的路径
options:?options
选项对象
callback: ?function
一个接受渲染结果回调函数,能够同步调用。
returns:function
返回值是HTML字符串
var pug = require('pug');
var html = pug.renderFile('path/to/file.pug', options);
// ...
自定义的过滤器
该对象的语义与选项中的过滤器语义相同,可是全局应用于全部Pug编译。 当pug.filters和options.filters中都存在过滤器时,filters选项优先
提示:不推荐使用此属性,而推荐使用滤镜选项。
pug代码中的标记属性看起来和HTML(带逗号),可是它的值只是普通的JavaScript。(注意:此页面上的示例使用竖线字符(|)进行空白控制。)
a(href='google.com') Google | | a(class='button' href='google.com') Google | | a(class='button', href='google.com') Google
生成结果:
<a href="google.com">Google</a> <a class="button" href="google.com">Google</a> <a class="button" href="google.com">Google</a>
普通的JavaScript也能够正常工做
- var authenticated = true body(class=authenticated ? 'authed' : 'anon')
<body class="authed"></body>
若是有多个属性,还能够把他们放在多行
input( type='checkbox' name='agreement' checked )
<input type="checkbox" name="agreement" checked="checked" />
若是你的JavaScript环境支持ES2015中的模板字符串(包含Node.js/io.js 1.0.0或后续版本),可使用模板字符串,若是属性值很长,这将会颇有用。
input(data-json=` { "very-long": "piece of ", "data": true } `)
<input data-json=" { "very-long": "piece of ", "data": true } " />
若是属性名中包可能会干扰JavaScript语法的含奇怪字符,请使用双引号或者单引号区分不一样的属性。包含[]和()(Angular2中常用)
//- In this case, `(click)` is treated as a //- function call instead of a attribute name, //- resulting in the unusual error. div(class='div-class' (click)='play()')
报错:
index.pug:4:11 2| //- function call instead of a attribute name, 3| //- resulting in the unusual error. > 4| div(class='div-class' (click)='play()') -----------------^ Syntax Error: Assigning to rvalue
正确的写法是:
div(class='div-class', (click)='play()') div(class='div-class' '(click)'='play()')
<div class="div-class" (click)="play()"></div> <div class="div-class" (click)="play()"></div>
注意:Pug/Jade的早期版本支持插值语法,例如:
a(href="/#{url}") Link
再也不支持此语法。 替代方法以下。 (有关Pug v2与先前版本之间其余不兼容性的更多信息,请参阅咱们的迁移指南。)
在属性中包含变量,可使用如下替代方法:
1.在JavaScript中使用属性
- var url = 'pug-test.html'; a(href='/' + url) Link | | - url = 'https://example.com/' a(href=url) Another link
结果以下:
<a href="/pug-test.html">Link</a> <a href="https://example.com/">Another link</a>
2.若是你的JavaScript环境支持ES2015(包含Node.js/io.js及更高版本),还可使用其语法来简化属性
- var btnType = 'info' - var btnSize = 'lg' button(type='button' class='btn btn-' + btnType + ' btn-' + btnSize) | | button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)
结果以下
<button class="btn btn-info btn-lg" type="button"></button> <button class="btn btn-info btn-lg" type="button"></button>
默认状况下,全部属性均被转义(即特殊字符被替换成转义序列)以防止攻击(例如:跨站攻击)。若是须要使用特殊符号,请使用 != 代替 =
div(escaped="<code>") div(unescaped!="<code>")
结果以下:
<div escaped="<code>"></div> <div unescaped="<code>"></div>
注意:未转义的代码是很危险的。必须确保清除用户输入中没有这种代码,以免跨站脚本攻击
pug中布尔类型的属性被自动转换为true,false。若是未指定任何值,则假定为true
input(type='checkbox' checked) | | input(type='checkbox' checked=true) | | input(type='checkbox' checked=false) | | input(type='checkbox' checked=true.toString())
结果以下:
<input type="checkbox" checked="checked" /> <input type="checkbox" checked="checked" /> <input type="checkbox" /> <input type="checkbox" checked="true" />
ps:用两个竖线分隔换行,pug代码比html代码还长!这是搞什么鸡毛啊。
像普通属性同样,style属性能够是一个字符串;同时它也能够是一个对象,这样生成样式会很方便。
a(style={color: 'red', background: 'green'})
<a style="color:red;background:green;"></a>
像普通属性同样,class属性能够是一个字符串;同时它也能够是一个对象,这样生成样式会很方便。
- var classes = ['foo', 'bar', 'baz'] a(class=classes) | | //- class属性能够merge多个 a.bang(class=classes class=['bing'])
<a class="foo bar baz"></a> <a class="bang foo bar baz bing"></a>
它也能够是将类名映射为true或false的对象。 这对于应用条件类颇有用
- var currentUrl = '/about' a(class={active: currentUrl === '/'} href='/') Home | | a(class={active: currentUrl === '/about'} href='/about') About
<a href="/">Home</a> <a class="active" href="/about">About</a>
可使用.classname语法建立class属性
a.button
<a class="button"></a>
因为div是一个经常使用的dom,若是声乐标签名,默认生成一个dom,以下:
.content
<div class="content"></div>
ps:这个比较人性化
使用id语法#idname能够建立元素
a#main-link
<a id="main-link"></a>
因为div是一个经常使用的dom,若是声乐标签名,默认生成一个dom,以下:
#content
<div id="content"></div>
使用&attributes语法能够建立多个自定义属性
div#foo(data-bar="foo")&attributes({'data-foo': 'bar'})
<div id="foo" data-bar="foo" data-foo="bar"></div>
上面例子中启示可使用object语法建立多个属性,也可使用变量灵活处理。(参考:Mixin属性)
- var attributes = {}; - attributes.class = 'baz'; div#foo(data-bar="foo")&attributes(attributes)
<div class="baz" id="foo" data-bar="foo"></div>
注意:使用&attributes属性不会自动转义,使用的时候必须注意验证用户输入,避免跨站攻击。使用mixin调用能够自动完成转义。
在JavaScript中case语法是和switch配合使用,pug中也可使用switch...case,以下:
- var friends = 10 case friends when 0 p you have no friends when 1 p you have a friend default p you have #{friends} friends
<p>you have 10 friends</p>
pug中的case语法和JavaScript中的switch相似,以下:
- var friends = 0 case friends when 0 when 1 p you have very few friends default p you have #{friends} friends
<p>you have very few friends</p>
可是和JavaScript中的case仍是有区别,pud中没有不是switch-case,而是case-when,若是不想在switch语句中输出任何内容,能够添加一个显式的break,以下:
- var friends = 0 case friends when 0 - break when 1 p you have very few friends default p you have #{friends} friends
这个case语句不会输出任何内容
case块语法也能够像下面这样:
- var friends = 1 case friends when 0: p you have no friends when 1: p you have a friend default: p you have #{friends} friends
<p>you have a friend</p>
Pug容许在模版中编写内联JavaScript代码。有三种类型的代码:Unbuffered(未缓存?),Buffered(缓冲?)和Unescaped Buffered(未转义的缓冲)
Unbuffered代码以-开头,注意这一句不会输出任何内容
- for (var x = 0; x < 3; x++) li item
<li>item</li> <li>item</li> <li>item</li>
固然,也支持块输出:
- var list = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis"] each item in list li= item
<li>Uno</li> <li>Dos</li> <li>Tres</li> <li>Cuatro</li> <li>Cinco</li> <li>Seis</li>
Buffered代码以=开头。它先计算JavaScript表达式并输出结果,为安全起见,Buffered代码首先转义为HTML
p = 'This code is <escaped>!'
<p>This code is <escaped>!</p>
它也能够之内联属性编写,并支持全部JavaScript表达式
p= 'This code is' + ' <escaped>!'
<p>This code is <escaped>!</p>
未转义的Buffered代码以!=开头。它计算JavaScript表达式并输出结果,可是输出的Html代码是未转义的,所以对用户而言是不安全的
p != 'This code is <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>
和转义的Buffered代码同样,它能够之内联形式编写属性,支持全部的JavaScript表达式
p!= 'This code is' + ' <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>
注意:未转义的Buffered代码多是很是危险的。必须处理用户输入,避免跨站攻击
缓冲注释和JavaScript中的单行注释同样,它的行为相似于标记标签,渲染的时候生成html注释。
// just some paragraphs p foo p bar
<!-- just some paragraphs--> <p>foo</p> <p>bar</p>
Pug还支持无缓冲注释,只需在注释开头加上字符-。这种注释只是对Pug代码自己进行注释,不会呈如今HTML中。
//- will not output within markup p foo p bar
<p>foo</p> <p>bar</p>
块注释方式以下:
body //- Comments for your template writers. Use as much text as you want. // Comments for your HTML readers. Use as much text as you want.
<body> <!--Comments for your HTML readers. Use as much text as you want.--> </body>
Pug中的条件注释和html同样,没有特殊的语法。(条件注释是为旧版本的Internet Explorer添加回退标记的一种特殊方法。)
Pug中以<开头被视为纯文本,普通的JavaScript条件注释在Pug中能够正常工做。
doctype html <!--[if IE 8]> <html lang="en" class="lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html lang="en"> <!--<![endif]--> body p Supporting old web browsers is a pain. </html>
<!DOCTYPE html> <!--[if IE 8]> <html lang="en" class="lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html lang="en"> <!--<![endif]--> <body> <p>Supporting old web browsers is a pain.</p> </body> </html>
Pug中条件语句能够不使用括号包裹
- var user = { description: 'foo bar baz' } - var authorised = false #user if user.description h2.green Description p.description= user.description else if authorised h2.blue Description p.description. User has no description, why not add one... else h2.red Description p.description User has no description
<div id="user"> <h2 class="green">Description</h2> <p class="description">foo bar baz</p> </div>
Pug还提供条件判断语句unless,它和if是相反的,以下两种判断是等价的。
unless user.isAnonymous p You're logged in as #{user.name}
if !user.isAnonymous p You're logged in as #{user.name}
doctype html
<!DOCTYPE html>
经常使用文档内省有一些快捷方式:
doctype html
<!DOCTYPE html>
doctype xml
<?xml version="1.0" encoding="utf-8" ?>
doctype transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
doctype strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
doctype frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
doctype 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
doctype basic
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
doctype mobile
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
doctype plist
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
还能够自定义本身的文档类型,以下:
doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">
除了在输出中缓冲外,Pug中的doctype还可能影响编译。 例如,自动关闭的标签是否以/>或>结尾取决因而否指定了HTML或XML。 布尔属性的输出也可能会受到影响。
若是因为其余缘由没法使用doctype关键字(例如,仅渲染HTML片断),可是仍然但愿指定模板的doctype,则能够经过doctype选项进行操做。
var pug = require('pug'); var source = 'img(src="foo.png")'; pug.render(source); // => '<img src="foo.png"/>' pug.render(source, {doctype: 'xml'}); // => '<img src="foo.png"></img>' pug.render(source, {doctype: 'html'}); // => '<img src="foo.png">'
过滤器容许在Pug模板中使用其余的语言,他们做为一块文本输入。要将选项传递给过滤器,须要在过滤器后的括号内添加(就像标记属性同样)例如:
:less(ieCompat=false)
全部JSTransformer模块均可以用做Pug过滤器。 流行的过滤器包括:babel,:uglify-js,:scss和:markdown-it。 请查看JSTransformer的文档,以了解特定过滤器支持的选项。
若是找不到适合您的用例的过滤器,则能够编写本身的自定义过滤器。
例如,若是您但愿可以在Pug模板中使用CoffeeScript和Markdown(使用Markdown-it渲染器),则首先要确保已安装如下插件:
$ npm install --save jstransformer-coffee-script $ npm install --save jstransformer-markdown-it
如今,您应该可以使用如下模板渲染:
:markdown-it(linkify langPrefix='highlight-') # Markdown Markdown document with http://links.com and ```js var codeBlocks; ``` script :coffee-script console.log 'This is coffee script'
<h1>Markdown</h1> <p>Markdown document with <a href="http://links.com">http://links.com</a> and</p> <pre><code class="highlight-js">var codeBlocks; </code></pre> <script> (function() { console.log('This is coffee script'); }).call(this); </script>
警告:过滤器在编译时渲染。 这使它们快速运行,但也意味着它们不能支持动态内容或选项。默认状况下,浏览器中的编译没法访问基于JSTransformer的筛选器,除非JSTransformer模块已明确经过CommonJS平台打包(例如Browserify或Webpack)。 实际上,您正当前这个页面正式使用使用Browserify打包使得过滤器在浏览器中可用。在服务器上预编译的模板没有此限制。
若是过滤器的内容比较短,甚至能够像使用标签那样使用过滤器。
p :markdown-it(inline) **BOLD TEXT** p. In the midst of a large amount of plain text, suddenly a wild #[:markdown-it(inline) *Markdown*] appeared.
<p><strong>BOLD TEXT</strong></p> <p>In the midst of a large amount of plain text, suddenly a wild <em>Markdown</em> appeared. </p>
在使用过滤器的时候,能够经过包含语法将外部文件包含进来。
能够在同一文本快上应用多个过滤器,为此只需在同一行使用过滤器语法。
过滤器以相反的顺序应用。 文本首先传递到最后一个过滤器; 而后,结果将传递到倒数第二个过滤器,依此类推。在如下示例中,脚本首先由babel转换,而后由cdata-js转换。
script :cdata-js:babel(presets=['es2015']) const myFunc = () => `This is ES2015 in a CD${'ATA'}`;
f.default.existsSync is not a function
经过filters选项,能够定义自定义过滤器
options.filters = { 'my-own-filter': function (text, options) { if (options.addStart) text = 'Start\n' + text; if (options.addEnd) text = text + '\nEnd'; return text; } };
p :my-own-filter(addStart addEnd) Filter Body
<p> Start Filter Body End </p>
包含语法容许在一个Pug文件中包含另外一个Pug文件。
//- index.pug doctype html html include includes/head.pug body h1 My Site p Welcome to my super lame site. include includes/foot.pug
//- includes/head.pug head title My Site script(src='/javascripts/jquery.js') script(src='/javascripts/app.js')
//- includes/foot.pug footer#footer p Copyright (c) foobar
结果以下:
<!DOCTYPE html> <html> <head> <title>My Site</title> <script src="/javascripts/jquery.js"></script> <script src="/javascripts/app.js"></script> </head> <body> <h1>My Site</h1> <p>Welcome to my super lame site.</p> <footer id="footer"> <p>Copyright (c) foobar</p> </footer> </body> </html>
若是使用绝对路径,可使用options.basedir变量拼接,不然按照相对当前文件的路径解析。
若是没有后缀,.pug将做为默认后缀。
包含的文件不是pug,则当作纯文原本处理。
//- index.pug doctype html html head style include style.css body h1 My Site p Welcome to my super lame site. script include script.js
/* style.css */ h1 { color: red; }
// script.js console.log('You are awesome');
<!DOCTYPE html> <html> <head> <style> /* style.css */ h1 { color: red; } </style> </head> <body> <h1>My Site</h1> <p>Welcome to my super lame site.</p> <script> // script.js console.log('You are awesome'); </script> </body> </html>
能够将过滤器与当前Pug文件结合使用。
//- index.pug doctype html html head title An Article body include:markdown-it article.md
# article.md This is an article written in markdown.
<!DOCTYPE html> <html> <head> <title>An Article</title> </head> <body> <h1>article.md</h1> <p>This is an article written in markdown.</p> </body> </html>
Pug支持模板继承,模板继承经过关键字“block”和“extends”实现。在模板中,block关键字表示这个块在子模块中能够被替换。此过程是递归的。下面示例定义了头部,块内容和脚。
//- layout.pug html head title My Site - #{title} block scripts script(src='/jquery.js') body block content block foot #footer p some footer content
建立新Pug文件来继承上面的Pug模板,在新的文件中使用extends关键字来继承,而后Pug模板中的block块会被继承下来。
注意foot块没有定义,因此使用父模板中的fug块,输出“some footer content”。而其余块将在自身基础上继承父模板的内容。
//- page-a.pug extends layout.pug block scripts script(src='/jquery.js') script(src='/pets.js') block content h1= title - var pets = ['cat', 'dog'] each petName in pets include pet.pug
//- pet.pug p= petName
还能够覆盖某个块以提供其余的块,在下面例子中,content块中暴露了sidebar和primary块(可是子模块能够彻底覆盖掉content)
//- sub-layout.pug extends layout.pug block content .sidebar block sidebar p nothing .primary block primary p nothing
//- page-b.pug extends sub-layout.pug block content .sidebar block sidebar p nothing .primary block primary p nothing
Pug容许替换(默认),前置,后置一个块。
假设您但愿在每一个页面的标题块中都包含默认脚本。 您能够这样作:
//- layout.pug html head block head script(src='/vendor/jquery.js') script(src='/vendor/caustic.js') body block content
例如,如今考虑您的JavaScript游戏页面。 您须要一些与游戏相关的脚本以及这些默认脚本。 您能够简单地添加块:
//- page.pug extends layout.pug block append head script(src='/vendor/three.js') script(src='/game.js')
在使用append,prepend的时候能够省去block关键字,以下:
//- page.pug extends layout append head script(src='/vendor/three.js') script(src='/game.js')
Pug的模板继承是一项强大的功能,可以让您将复杂的页面模板结构拆分为更小,更简单的文件。 可是,若是将许多模板连接在一块儿,则可能会使页面复杂得不可维护。
请注意,只有命名块和混合定义能够出如今子模板的顶层(未缩进)。 这个很重要! 父模板定义页面的总体结构,子模板只能附加,添加或替换特定的标记和逻辑块。 若是子模板试图在块外添加内容,Pug将没法知道将其放置在最终页面的何处。
使用未缓冲的代码,若是须要在子模块中使用变量,则可使用下面几种不一样的方法:
出于一样的缘由,Pug的缓冲注释不能出如今扩展模板的顶层:它们产生的HTML注释在生成的HTML中无处渲染。 (可是,无缓冲的Pug注释仍然能够)
Pug提供多种方式在html中插入一个值。
下面例子中title,author,theGreat变量做为本地变量被插入到代码中。
- var title = "On Dogs: Man's Best Friend"; - var author = "enlore"; - var theGreat = "<span>escape!</span>"; h1= title p Written with love by #{author} p This will be safe: #{theGreat}
<h1>On Dogs: Man's Best Friend</h1> <p>Written with love by enlore</p> <p>This will be safe: <span>escape!</span></p>
title演示的是最基本的使用方法,再是在#{}中使用变量将会被转义,并将结果缓冲到要渲染的模板中。
还可使用表达式,只要是合法的,任何地方均可以使用。
- var msg = "not my inside voice"; p This is #{msg.toUpperCase()}
<p>This is NOT MY INSIDE VOICE</p>
Pug能够自动找出判断表达式是否结束,甚至能够包含未转义的符号,例如}
p No escaping for #{'}'}!
<p>No escaping for }!</p>
若是想在html中输出#{,能够将其转义,或者使用插值。
p Escaping works with \#{interpolation} p Interpolation works with #{'#{interpolation}'} too!
<p>Escaping works with #{interpolation}</p> <p>Interpolation works with #{interpolation} too!</p>
能够将未转义的字符串缓冲在模板中。
- var riskyBusiness = "<em>Some of the girls are wearing my mother's clothing.</em>"; .quote p Joel: !{riskyBusiness}
<div class="quote"> <p>Joel: <em>Some of the girls are wearing my mother's clothing.</em></p> </div>
注意:若是原内容来自用户输入,则将未转义的内容缓冲到模板中可能带来很大的风险。永远不要相信用户的输入。
不只可使用JavaScript插入变量,还能够在Pug内容中插入标签,以下:
p. This is a very long and boring paragraph that spans multiple lines. Suddenly there is a #[strong strongly worded phrase] that cannot be #[em ignored]. p. And here's an example of an interpolated tag with an attribute: #[q(lang="es") ¡Hola Mundo!]
<p>This is a very long and boring paragraph that spans multiple lines. Suddenly there is a <strong>strongly worded phrase</strong> that cannot be <em>ignored</em>.</p> <p>And here's an example of an interpolated tag with an attribute: <q lang="es">¡Hola Mundo!</q></p>
您能够经过编写与Pug内联的HTML标签来完成相同的事,可是,编写Pug的目的是什么? 将内嵌的Pug标签声明包装在#[]中,它将被评估并缓冲到其包含标签的内容中。
默认状况下,Pug会删除标记以前和以后全部的空格,以下:
p | If I don't write the paragraph with tag interpolation, tags like strong strong | and em em | might produce unexpected results. p. If I do, whitespace is #[strong respected] and #[em everybody] is happy.
<p>If I don't write the paragraph with tag interpolation, tags like<strong>strong</strong>and<em>em</em>might produce unexpected results.</p> <p>If I do, whitespace is <strong>respected</strong> and <em>everybody</em> is happy.</p>
有关此主题的更多讨论,请参见Plain Text。
Pug中支持两种方式的循环输出:each和while
Pug中第一种循环输出语法each能够迭代模板中的数组和对象。
ul each val in [1, 2, 3, 4, 5] li= val
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul>
循环中能够从第二个参数中获取当前index
ul each val, index in ['zero', 'one', 'two'] li= index + ': ' + val
<ul> <li>0: zero</li> <li>1: one</li> <li>2: two</li> </ul>
Pug中甚至能够迭代中获取对象的key
ul each val, index in {1:'one',2:'two',3:'three'} li= index + ': ' + val
<ul> <li>1: one</li> <li>2: two</li> <li>3: three</li> </ul>
要迭代的对象或数组只是纯JavaScript。 所以,它能够是变量,也能够是函数调用的结果,或者几乎是其余任何东西。
- var values = []; ul each val in values.length ? values : ['There are no values'] li= val
<ul> <li>There are no values</li> </ul>
若是数组或对象不包含要迭代的值,则还能够添加一个else块,该块将被执行。 如下等效于上面的示例:
- var values = []; ul each val in values li= val else li There are no values
<ul> <li>There are no values</li> </ul>
还可使用for关键字代替each,效果是同样的。
还可使用while来迭代,以下:
- var n = 0; ul while n < 4 li= n++
<ul> <li>0</li> <li>1</li> <li>2</li> <li>3</li> </ul>
Mixins容许建立可重用的块。
//- Declaration mixin list ul li foo li bar li baz //- Use +list +list
<ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul> <ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul>
Mixins容许传入参数
mixin pet(name) li.pet= name ul +pet('cat') +pet('dog') +pet('pig')
<ul> <li class="pet">cat</li> <li class="pet">dog</li> <li class="pet">pig</li> </ul>
Mixins还可使用Pug块做为内容:
mixin article(title) .article .article-wrapper h1= title if block block else p No content provided +article('Hello world') +article('Hello world') p This is my p Amazing article
<div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> <p>No content provided</p> </div> </div> <div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> <p>This is my</p> <p>Amazing article</p> </div> </div>
混合还能够传入一个隐式参数,能够用来给属性赋值
mixin link(href, name)
//- attributes == {class: "btn"}
a(class!=attributes.class href=href)= name
+link('/foo', 'foo')(class="btn")
<a class="btn" href="/foo">foo</a>
注意:默认状况下,属性中的值已被转义! 您应该使用!=以免再次转义它们。 (另请参见未转义的属性。)
能够在混合中使用&attributes:
mixin link(href, name) a(href=href)&attributes(attributes)= name +link('/foo', 'foo')(class="btn")
<a class="btn" href="/foo">foo</a>
注意:语法+ link(class =“ btn”)也是有效的,而且等价于+ link()(class =“ btn”),由于Pug会尝试检测括号的内容是属性仍是参数。 可是,建议您使用第二种语法,由于您没有明确传递任何参数,而且确保第一个括号是参数列表。
还能够设置参数的默认值,和ES6中设置函数的默认参数值是相似的:
//- Declaration mixin article(title='Default Title') .article .article-wrapper h1= title //- Use +article() +article('Hello world')
<div class="article"> <div class="article-wrapper"> <h1>Default Title</h1> </div> </div> <div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> </div> </div>
在Mixins中可使用解析参数来传递多个参数
mixin list(id, ...items) ul(id=id) each item in items li= item +list('my-list', 1, 2, 3, 4)
<ul id="my-list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
Pug提供了四种获取纯文本的方法-即将未经处理的代码,文本渲染在HTML中,有时候会颇有用。
纯文本仍然使用标记和字符串插值,但该行的第一个单词不是Pug标记。 而且因为不会转义纯文本,所以您还能够包括文字HTML。
一个常见的缺陷是在渲染的HTML中使用空白,将在后面讨论。
插入纯文本最先的方式是使用内敛标签。第一个词是标签名,后面全部内容都是标签的内容。若是内容很短或者不介意这一行内容太长,这样是没有任何问题的。
p This is plain old <em>text</em> content.
<p>This is plain old <em>text</em> content.</p>
当整行以左尖括号(<)开头时,它们也被视为纯文本,有时不方便的地方编写文字HTML标签颇有用。 例如,一种用例是条件注释。 因为文字HTML标记不会获得处理,所以与Pug标记不一样,它们不会自动关闭。
<html> body p Indenting the body tag here would make no difference. p HTML itself isn't whitespace-sensitive. </html>
<html> <body> <p>Indenting the body tag here would make no difference.</p> <p>HTML itself isn't whitespace-sensitive.</p> </body> </html>
将纯文本添加到模板的另外一种方法是在行的前面加上竖线字符(|)。 如咱们稍后在“空白内容”部分中所述,此方法对于将纯文本与内联标签混合颇有用。
p | The pipe always goes at the beginning of its own line, | not counting indentation.
<p>The pipe always goes at the beginning of its own line, not counting indentation.</p>
一般,您可能但愿标签中包含大块文本。 一个很好的例子是在script和style标签中编写JavaScript和CSS代码。 为此,只需添加一个逗号, 若是标签具备属性,则在标签名称以后,或者在右括号以后。
注意在tag和逗号之间不能有空格,标签的纯文本内容必须缩进一级。
script. if (usingPug) console.log('you are awesome') else console.log('use pug')
<script> if (usingPug) console.log('you are awesome') else console.log('use pug') </script>
还能够在tag标签内部再使用逗号建立一个块:
div
p This text belongs to the paragraph tag.
br
.
This text belongs to the div tag.
<div> <p>This text belongs to the paragraph tag.</p><br/>This text belongs to the div tag.</div>
空格控制
处理HTML中的空白多是学习Pug最麻烦的地方,不过掌握窍门以后就很容易了。只须要记住两点:
因此,Pug删除了标签之间的空格,保留标签内部的空格。这样能够控制是否能够在tag或者纯文本中出的空格。甚至单词之间的空格。
| You put the em em pha | sis on the wrong syl em la | ble.
You put the em<em>pha</em>sis on the wrong syl<em>la</em>ble.
去掉空格须要考虑控制标签和文本是否链接在一块儿。
a ...sentence ending with a link
| .
<a>...sentence ending with a link</a>.
若是须要添加空格,参考下面方法
添加一个或者多个竖线,表示空白的管道符,在HTMl渲染的时候就会有空格出现。
| Don't | button#self-destruct touch | | me!
Don't <button id="self-destruct">touch</button> me!
若是你的内嵌标签不须要太多属性,能够在纯文本中使用标签值或者HTML
p. Using regular tags can help keep your lines short, but interpolated tags may be easier to #[em visualize] whether the tags and text are whitespace-separated.
<p>Using regular tags can help keep your lines short, but interpolated tags may be easier to <em>visualize</em> whether the tags and text are whitespace-separated.</p>
根据须要的空格,能够在文本的开头(在块缩进,竖线字符和/或标记以后)添加一个额外的空格。 或者,您能够在文本末尾添加尾随空格。
| Hey, check out a(href="http://example.biz/kitteh.png") this picture | of my cat!
| Hey, check out
a(href="http://example.biz/kitteh.png") this picture
| of my cat!
上面的解决方案能够很好地工做,可是确定会有些危险:默认状况下,许多代码编辑器都会在保存时删除尾随空格。 你的同时可能必须配置编辑器,以防止自动删除部空格。