SitePoint Premium gives you an entire collection of books covering developer essentials like Pug, Gulp, Git and more. Join now.
SitePoint Premium为您提供了一整套书籍,涵盖了Pug,Gulp,Git等开发人员的必备知识。 现在加入 。
As web designers or developers, we likely all have to write our fair share of HTML. And while this is not the most difficult task, it can often feel a little boring or repetitive. HTML is also static, which means that if you want to display dynamic data (fetched from an API, for example), you invariably end up with a mishmash of HTML stings inside JavaScript. This can be a nightmare to debug and to maintain.
作为网页设计师或开发人员,我们可能都必须编写我们应有HTML。 尽管这不是最困难的任务,但它通常会感到有些无聊或重复。 HTML也是静态的,这意味着,如果要显示动态数据(例如,从API中获取),则不可避免地会在JavaScript中产生大量HTML字符串。 这可能是调试和维护的噩梦。
This is where Pug comes in. Pug is a template engine for Node and for the browser. It compiles to HTML and has a simplified syntax, which can make you more productive and your code more readable. Pug makes it easy both to write reusable HTML, as well as to render data pulled from a database or API.
这是Pug进入的地方。Pug是Node和浏览器的模板引擎。 它可以编译为HTML并具有简化的语法,从而可以提高工作效率并提高代码的可读性。 Pug使编写可重用HTML以及呈现从数据库或API提取的数据变得容易。
In this guide, I’ll demonstrate how to get up and running with Pug. We’ll start by installing it from npm, go over its basic syntax and then look at several examples of using JavaScript in Pug. Finally, we’ll explore a couple of Pug’s more advanced features by building a simple Node/Express project which uses Pug as its template engine.
在本指南中,我将演示如何使用Pug启动和运行。 我们将从npm安装它开始,介绍其基本语法,然后看几个在Pug中使用JavaScript的示例。 最后,我们将通过构建一个简单的Node / Express项目(使用Pug作为其模板引擎)来探索Pug的一些更高级的功能。
Before we start looking at Pug, let’s take a second to understand the concepts involved.
在开始研究Pug之前,让我们花点时间了解其中涉及的概念。
A template engine is a program which is responsible for compiling a template (that can be written using any one of a number of languages) into HTML. The template engine will normally receive data from an external source, which it will inject into the template it’s compiling. This is illustrated by the following diagram.
模板引擎是负责将模板(可以使用多种语言中的任何一种编写)编译为HTML的程序。 模板引擎通常会从外部来源接收数据,并将其注入正在编译的模板中。 下图说明了这一点。
This approach allows you to reuse static web page elements, while defining dynamic elements based on your data. It also facilitates a separation of concerns, keeping your application logic isolated from your display logic.
这种方法使您可以重用静态网页元素,同时根据数据定义动态元素。 它还有利于分离关注点,使您的应用程序逻辑与显示逻辑保持隔离。
You’re more likely to benefit from a template engine if your site or web application is data driven — such as a staff directory for administering employees, a web store that lists various products for users to buy, or a site with dynamic search functionality.
如果您的站点或Web应用程序是数据驱动的,则您更有可能从模板引擎中受益-例如,用于管理员工的人员目录,列出供用户购买的各种产品的Web商店或具有动态搜索功能的站点。
You won’t need a template engine if you’re fetching a small amount of data from an API (in which case you can just use JavaScript’s native template strings), or if you’re making a small static site.
如果您要从API提取少量数据(在这种情况下,您只能使用JavaScript的本机模板字符串 ),或者您要建立一个小型静态网站,则不需要模板引擎。
It’s also worth noting that Pug used to be called Jade until it was forced to change its name due to a trademark claim in 2015. The name change took effect with version 2.0.
还要指出的是,Pug在2015年因商标主张而被迫更改名称之前曾经被称为Jade。名称更改从2.0版开始生效。
There’s still a lot of Jade-related material available online. And while some of it’s probably still quite valid, the fact that the name change coincided with a major version bump means that Pug’s syntax has several differences, deprecations, and removals compared to its predecessor. These are documented here.
在线上仍然有很多与玉有关的资料。 虽然其中一些可能仍然很有效,但名称更改与主要版本颠簸同时发生的事实意味着,Pug的语法与其前身相比具有若干区别,弃用和删除。 这些都记录在这里 。
If you’re interested in finding out more, you can read the original name change announcement in this GitHub issue. Otherwise, just be sure to add the word “template” to your Pug-related Google searches to avoid the results being full of pooches.
如果您想了解更多信息,可以阅读本GitHub问题中的原始名称更改公告。 否则,只需确保在与Pug相关的Google搜索中添加“模板”一词即可避免搜索结果充满歧义。
Before we can get to writing some Pug, we’ll need to install Node, npm (which comes bundled with Node) and the pug-cli package.
在开始编写一些Pug之前,我们需要安装Node,npm(与Node捆绑在一起)和pug-cli软件包 。
There’s a couple options for installing Node/npm. Either head on over to the project’s home page and download the correct binaries for your system, or use a version manager such as nvm. I would recommend using a version manager where possible, as this will allow you to install different Node versions and switch between them at will. It will also negate a bunch of potential permissions errors.
有两个安装Node / npm的选项。 转到项目的主页并为您的系统下载正确的二进制文件,或者使用版本管理器(例如nvm) 。 我建议尽可能使用版本管理器,因为这将允许您安装不同的Node版本并在它们之间随意切换。 它还将消除一堆潜在的权限错误。
You can check out our tutorial “Installing Multiple Versions of Node.js Using nvm” for a more in-depth guide.
您可以查看我们的教程“ 使用nvm安装多个版本的Node.js ”以获取更深入的指导。
Once Node and npm are installed on your system, you can install the pug-cli
package like so:
一旦在系统上安装了Node和npm,就可以像下面这样安装pug-cli
软件包:
npm i -g pug-cli
You can check that the install process ran correctly by typing pug --version
into a terminal. This will output the version of Pug and the version of the CLI that you have installed.
您可以通过在终端中键入pug --version
来检查安装过程是否正确运行。 这将输出Pug的版本和已安装的CLI的版本。
At the time of writing, this was as follows:
在撰写本文时,内容如下:
$ pug --version
pug version: 2.0.3
pug-cli version: 1.0.0-alpha6
If your editor doesn’t offer syntax highlighting for Pug, it’d be a good idea to look for an extension to add this functionality.
如果您的编辑器不提供Pug的语法突出显示功能,那么最好找一个扩展来添加此功能。
I’m currently using Sublime Text 3 and, out of the box, this is what a .pug
file looks like:
我目前正在使用Sublime Text 3, .pug
文件的外观如下:
To remedy this, one can install the Sublime Pug package:
为了解决这个问题,可以安装Sublime Pug软件包 :
Syntax highlighting will make it much easier to work with Pug files, especially those of any length.
突出显示语法将使处理Pug文件(尤其是任何长度的文件)更加容易。
If you’d like to follow along with the simpler examples in this tutorial, you can also run them in various online code playgrounds.
如果您想按照本教程中的简单示例进行操作,也可以在各种在线代码游乐场中运行它们。
CodePen, for example, has Pug support baked right in. Simply create a new pen, then select Settings > HTML and choose Pug as your preprocessor. This will allow you to enter Pug code into the HTML pane and see the result appear in real time.
例如, CodePen已立即支持Pug。只需创建一个新笔,然后选择“设置” >“ HTML ” ,然后选择Pug作为预处理器。 这将允许您在HTML窗格中输入Pug代码,并实时看到结果。
As an added bonus, you can click on the down arrow in the HTML pane and select View Compiled HTML to see the markup that Pug has generated.
另外,您可以单击HTML窗格中的向下箭头,然后选择“ 查看编译HTML”以查看Pug生成的标记。
Now that we’ve got Pug installed, let’s try it out. Create a new directory named pug-examples
and change into it. Then create a further directory called html
and a file called index.pug
:
现在我们已经安装了Pug,让我们尝试一下。 创建一个名为pug-examples
的新目录并将其更改。 然后创建另一个名为html
目录和一个名为index.pug
的文件:
mkdir -p pug-examples/html
cd pug-examples
touch index.pug
Note: the touch
command is Linux/macOS specific. Windows users would do echo.> index.pug
to achieve the same thing.
注意: touch
命令特定于Linux / macOS。 Windows用户会执行echo.> index.pug
来实现相同的目的。
The way this is going to work is that we’ll write our Pug code in index.pug
and have the pug-cli
watch this file for changes. When it detects any, it will take the contents of index.pug
and render it as HTML in the html
directory.
这将起作用的方式是,我们将在index.pug
文件index.pug
编写我们的Pug代码, index.pug
pug-cli
监视该文件中的更改。 当检测到任何内容时,它将获取index.pug
的内容,并将其呈现为html
目录中的html
。
To kick this off, open a terminal in the pug-examples
directory and enter this:
要开始此操作,请在pug-examples
目录中打开一个终端,然后输入以下内容:
pug -w . -o ./html -P
You should see something like the following:
您应该看到类似以下的内容:
watching index.pug
rendered /home/jim/Desktop/pug-examples/html/index.html
Note: in the above command, the -w
option stands for watch, the dot tells Pug to watch everything in the current directory, -o ./html
tells Pug to output its HTML in the html
directory and the -P
option prettifies the output.
注意:在上面的命令中, -w
选项代表watch,点告诉Pug观看当前目录中的所有内容, -o ./html
告诉Pug在html
目录中输出其HTML, -P
选项使输出-o ./html
。
Now let’s create the page from the screenshot above (the one complaining about the lack of syntax highlighting). Enter the following into index.pug
:
现在,让我们从上面的屏幕截图创建页面(该页面抱怨缺少语法突出显示)。 在index.pug
输入以下index.pug
:
doctype html
html(lang='en')
head
title Hello, World!
body
h1 Hello, World!
div.remark
p Pug rocks!
Save pug.index
and then inspect the contents of ./html/index.html
. You should see the following:
保存pug.index
,然后检查./html/index.html
的内容。 您应该看到以下内容:
Hello, World!
Hello, World!
Pug rocks!!
Not bad, eh? The Pug CLI has taken our Pug file and rendered it as regular HTML.
还不错吧? Pug CLI已获取我们的Pug文件,并将其呈现为常规HTML。
This example serves to highlight a couple of important points about Pug. Firstly, it is whitespace sensitive, which means that Pug uses indentation to work out which tags are nested inside each other. For example:
此示例旨在突出有关Pug的几个要点。 首先,它对空格敏感 ,这意味着Pug使用缩进来找出哪些标签相互嵌套。 例如:
div.remark
p Pug rocks!!
The code above produces this:
上面的代码产生了这个:
Pug rocks!!
Now take this code:
现在使用以下代码:
div.remark
p Pug rocks!!
This produces the following:
这将产生以下结果:
Pug rocks!!
It doesn’t really matter what level of indentation you use (you can even use tabs if you have to), but it’s highly recommended that you keep the level of indentation consistent. In this article I’ll be using two spaces.
使用哪种缩进级别并不重要(如果需要,甚至可以使用制表符),但是强烈建议您保持一致的缩进级别。 在本文中,我将使用两个空格。
Secondly, Pug doesn’t have any closing tags. This will obviously save you a fair few keystrokes and affords Pug a clean and easy-to-read syntax.
其次, Pug没有任何结束标记 。 显然,这将为您节省一些击键,并为Pug提供一种简洁易懂的语法。
Now that we’ve got a handle on some basic Pug, let’s quickly go over its syntax. If any of this seems confusing, or you’d like to go more in-depth, be sure to consult the project’s excellent documentation.
既然我们已经掌握了一些基本的Pug,现在让我们快速了解一下它的语法。 如果其中任何一个看起来令人困惑,或者您想进一步深入,请确保查阅该项目的出色文档 。
You can use Pug to generate a number of document type declarations.
您可以使用Pug生成许多文档类型声明。
For example doctype html
will compile to , the standard HTML5 doctype, whereas
doctype strict
will give us . Pug will do its best to ensure that its output is valid for the document type.
例如doctype html
将编译为标准HTML5 doctype ,而
doctype strict
将为我们提供 。 Pug将尽力确保其输出对于文档类型有效。
As mentioned, Pug doesn’t have any closing tags and relies on indentation for nesting. This might take a small amount of getting used to, but once you do, it makes for clean and readable code. By way of an example:
如前所述,Pug没有任何结束标记,并且依赖缩进进行嵌套。 这可能需要一点时间来习惯,但是一旦您习惯了,它就会使代码清晰易读。 举个例子:
nav
navbar-default div
h1 My Website!
ul
li
a Home
li
a Page 1
li
a Page 2
input
The code above compiles to this:
上面的代码编译为此:
Notice that Pug is smart enough to close any self-closing tags (such as the element) for us.
请注意,Pug足够聪明,可以为我们关闭任何自动关闭的标签(例如元素)。
Classes and IDs are expressed using a .className
and #IDname
notation. For example:
类和ID使用.className
和#IDname
表示法表示。 例如:
nav#navbar-default
div.container-fluid
h1.navbar-header My Website!
Pug also offers us a handy shortcut. If no tag is specified, it will assume a 帕格还为我们提供了方便的捷径。 如果未指定标签,它将采用 Both of these compile to: 这两个都编译为: Attributes are added using brackets: 使用括号添加属性: This results in the following: 结果如下: There’s a lot more to say about attributes. For example, you could use JavaScript to include variables in your attributes, or assign an array of values to an attribute. We’ll get on to using JavaScript in Pug in the next section. 关于属性还有很多要说的。 例如,您可以使用JavaScript在属性中包含变量,或为属性分配值数组。 在下一节中,我们将继续在Pug中使用JavaScript。 Pug provides various methods for adding plain text directly into the rendered HTML. Pug提供了多种将纯文本直接添加到呈现HTML中的方法。 We’ve already seen how to add plain text inline: 我们已经了解了如何内联添加纯文本: Another way is to prefix a line with a pipe character ( 另一种方法是用竖线字符( This gives us the following: 这给我们以下内容:
You are logged in as
[email protected]
When dealing with large blocks of text, you can just ad a dot 处理大块文字时,您可以仅添加一个点 This results in: 结果是:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
Finally, comments can be added like so: 最后,可以像这样添加注释: This comment will be added to the rendered HTML: 此注释将添加到呈现HTML中: You start a comment like so: 您开始这样的评论: When you do this, the comment will remain in the Pug file but won’t appear in the HTML. 执行此操作时,注释将保留在Pug文件中,但不会出现在HTML中。 Comments must appear on their own line. Here, the comment will be treated as plain text: 注释必须出现在自己的行上。 在这里,注释将被视为纯文本: Multiline comments are possible, too: 多行注释也是可能的: Below you can find a demo of a Bootstrap-style layout which demonstrates the techniques we’ve discussed so far: 在下面,您可以找到Bootstrap样式的布局演示,该演示演示了到目前为止我们讨论的技术: See the Pen Basic Pug Demo by SitePoint (@SitePoint) on CodePen. 请参阅CodePen上的SitePoint ( @SitePoint )的Pen Basic Pug演示 。 One of the great things about Pug is the ability to run JavaScript in your templates. This makes it easy to insert variables into our templates, iterate over arrays and objects, conditionally render HTML, and much more. Pug的一大优点是能够在模板中运行JavaScript。 这样可以很容易地将变量插入模板中,遍历数组和对象,有条件地呈现HTML等。 This is an important distinction to be aware of before using JavaScript in Pug. 这是在Pug中使用JavaScript之前要意识到的重要区别。 Unbuffered code starts with a minus ( 未缓冲的代码以减号( Buffered code, on the other hand, starts with an equals ( 另一方面, 缓冲的代码以等号( The code above compiles to this: 上面的代码编译为此: Two to the power of ten is: 1024 For reasons of security, buffered code is HTML escaped. 出于安全考虑,缓冲的代码是HTML转义的。 The code above compiles to this: 上面的代码编译为此: <script>alert("Hi")</script> String interpolation is the process of replacing one or more placeholders in a template with a corresponding value. As we’ve just seen, buffered input offers one method of doing this. Another is using 字符串插值是将模板中的一个或多个占位符替换为相应值的过程。 正如我们已经看到的,缓冲输入提供了一种执行此操作的方法。 另一个正在使用 The code above compiles to this: 上面的代码编译为此: Hi jim As the curly brackets can contain any valid JavaScript expression, this opens up a bunch of possibilities: 由于大括号可以包含任何有效JavaScript表达式,因此开辟了很多可能性: This compiles to: 编译为: Hi Jim It’s also possible to render unescaped values into your templates using 也可以使用 Note: when you want to assign the value held in a variable to an element’s attribute, you can omit the 注意:当您要将变量中包含的值分配给元素的属性时,可以省略 Pug’s Pug的 This results in the following: 结果如下: You can also use it to iterate over the keys in an object: 您还可以使用它来遍历对象中的键: This results in: 结果是: Pug also lets you provide an else block that will be executed if the array or object is empty: Pug还允许您提供一个else块,如果数组或对象为空,则将执行该块: Finally, note that you can use 最后,请注意,您可以使用 Conditionals offer a very handy way of rendering different HTML depending upon the result of a JavaScript expression: 条件提供了一种非常方便的方式来呈现不同HTML,这取决于JavaScript表达式的结果: In this example, we’re checking whether the 在此示例中,我们正在检查 Below you can find a demo of some of the techniques we’ve discussed in this section. This showcases Pug’s benefits somewhat more than the previous demo, as all we need to do to add further employees is to add further objects to our 在下面,您可以找到我们在本节中讨论的一些技术的演示。 这展示了Pug的好处比以前的演示要多一些,因为我们需要做的增加更多员工的工作就是在 See the Pen JavaScript in Pug Demo by SitePoint (@SitePoint) on CodePen. 请参阅CodePen上的SitePoint ( @SitePoint )的Pug演示中的Pen JavaScript 。 Now that we have a reasonable idea of Pug’s syntax and how it works, let’s finish off by building a small Express.js app to demonstrate a couple of Pug’s more advanced features. 现在,我们对Pug的语法及其工作原理有了一个合理的了解,让我们最后通过构建一个小型Express.js应用程序来演示Pug的一些更高级的功能。 The code for this example is available on GitHub. 该示例的代码可在GitHub上找到 。 Note: if you’ve not used Express before, no worries. It’s a web framework for Node.js which provides a robust set of features for building web apps. If you’d like to find out more, check out our getting started with Express tutorial. 注意:如果您以前从未使用过Express,则无需担心。 这是Node.js的Web框架,提供了用于构建Web应用程序的一组强大功能。 如果您想了解更多信息,请查看我们的Express入门教程 。 First off, let’s create a new project and install Express: 首先,让我们创建一个新项目并安装Express: Next create an 接下来在 Then add the following: 然后添加以下内容: Here we’re declaring a route ( 在这里,我们声明一条路由( If you see something like this, then things have gone to plan: 如果您看到类似这样的信息,那么说明事情已经计划好了: This Express app won’t do anything too spectacular. We’ll be building a simple staff directory which fetches a list of employees from a database and displays them in a table. For that to happen, we’ll need a database and some data. 这个Express应用程式不会做得太壮观。 我们将构建一个简单的职员目录,该目录将从数据库中获取职员列表并将其显示在表格中。 为此,我们需要一个数据库和一些数据。 However … installing and configuring a database is a little heavy handed for this small example, so I’m going to use a package called json-server. This will allow us to create a 但是…对于这个小例子,安装和配置数据库有点繁琐,因此我将使用一个名为json-server的软件包。 这将使我们能够创建 Let’s install it: 让我们安装它: Now create the aforementioned 现在,在项目的根目录中创建上述的 Finally, we need some JSON to populate it. We’ll use the Random User Generator, which is a free, open-source API for generating random user data. Twenty-five people should do for our example, so head over to 最后,我们需要一些JSON来填充它。 我们将使用Random User Generator ,这是一个免费的开源API,用于生成随机用户数据。 我们的示例应由25个人完成,因此请转到 Finally, start the server in a second terminal window with: 最后,使用以下命令在第二个终端窗口中启动服务器: This will cause json-server to start up on port 3001 and watch our database file for changes. 这将导致json-server在端口3001上启动,并查看我们的数据库文件中的更改。 Express has excellent support for using Pug, so very little configuration is necessary. Express对使用Pug具有出色的支持,因此几乎不需要任何配置。 First, let’s add Pug to our project: 首先,让我们将Pug添加到我们的项目中: Then in 然后在 Next, create a 接下来,创建一个 Add some content to that file: 向该文件添加一些内容: Then alter 然后像这样修改 Finally, restart the Node server, then refresh your browser and you should see this: 最后,重新启动节点服务器,然后刷新浏览器,您应该看到以下内容: And that’s it. You’re good to go. 就是这样。 你很好 The next task on the list is to hand some data to the Pug template to display. To do that, we’ll need a method of fetching the data from the json-server. Unfortunately, the fetch API isn’t implemented in Node, so let’s use axios, the popular HTTP client instead: 列表上的下一个任务是将一些数据交给Pug模板进行显示。 为此,我们需要一种从json服务器获取数据的方法。 不幸的是,fetch API并未在Node中实现,因此我们使用流行的HTTP客户端axios代替: Then alter 然后像这样修改 There’s a couple of things going on here. We’ve turned our route handler into an async function, so that we can wait for the employee data to be returned from json-server before handing it off to the template. 这里发生了几件事。 我们已经将路由处理程序变成了async函数 ,以便我们可以等待json-server返回员工数据,然后再将其传递给模板。 Then we render the index as before, but this time we pass it an object literal containing all of our data. 然后我们像以前一样渲染索引,但是这次我们将包含所有数据的对象常量传递给它。 Note: you have to restart the Node server every time you make a change to 注意:每次更改 Now for the Pug. Change 现在给哈巴狗。 将 There’s hopefully nothing surprising going on here. We’re using semantic-ui-css for some styling, as well as a couple of styles of our own. 希望这里没有令人惊讶的事情。 我们将语义ui-css用于某些样式以及我们自己的几种样式。 Then, in the table body we’re iterating over the array of 然后,在表主体中,我们遍历从 At the bottom of the page is a footer with our copyright claim and the current year. 页面底部是页脚,其中包含我们的版权声明和当前年份。 If you refresh the page now, you should see this: 如果现在刷新页面,应该看到以下内容: This is pretty nice already, but to round things off, I’m going to demonstrate how to structure our views to offer maximum flexibility as the project grows. 这已经很不错了,但是为了解决问题,我将演示如何构建我们的视图,以随着项目的发展提供最大的灵活性。 Let’s start off by creating a 让我们从在 Then add the following: 然后添加以下内容: What we’ve done here is create a layout file than can be extended by other Pug files within our project. When you have a large number of Pug files, this saves a considerable amount of code. 我们在这里所做的是创建一个布局文件,该文件可以由我们项目中的其他Pug文件扩展。 当您有大量的Pug文件时,这可以节省大量代码。 The way this works is that we’ve defined two blocks of content ( 运作方式是我们定义了两个内容模板( Now we can tell our 现在我们可以告诉我们的 The result is the same as we had before, but the code now has a better structure. 结果与以前相同,但是代码现在具有更好的结构。 Mixins allow you to create reusable blocks of Pug. We can use this to extract our table row into its own file. Mixins允许您创建可重复使用的Pug块。 我们可以使用它来将表行提取到其自己的文件中。 Create a folder called 在 Mixins are declared using the 使用 Now alter 现在像这样更改 As you can see, we’re importing the mixin at the top of the file. We then call it by prefixing its name with a plus symbol and pass it our 如您所见,我们在文件顶部导入了mixin。 然后,我们通过在名称前加上加号来对其进行调用,并将其传递给我们的 This is overkill for our little app, but it demonstrates a very useful feature of Pug which allows us to write reusable code. 对于我们的小应用程序来说,这太过分了,但是它展示了Pug的一个非常有用的功能,它允许我们编写可重用的代码。 Well done if you’ve made it this far! We’ve covered a lot of ground in this tutorial. We’ve looked at installing Pug, its basic syntax, its JavaScript support and constructs for iteration and conditional rendering. Finally, we built a fully functioning Express app which pulls data from a remote source and feeds it to a Pug template. 做得好,如果你已经做到了! 在本教程中,我们已经涵盖了很多基础知识。 我们已经研究了安装Pug,其基本语法,其JavaScript支持以及用于迭代和条件渲染的构造。 最后,我们构建了一个功能全面的Express应用程序,该应用程序从远程源中提取数据并将其提供给Pug模板。 There’s still a lot more that Pug can do. I’d encourage you to check out its excellent documentation and to just start using it in your projects. You can also use it with several modern JS frameworks, such as React or Vue, and it has even been ported to several other languages. 哈巴狗还有很多事情可以做。 我鼓励您查看其出色的文档,并开始在您的项目中使用它。 您还可以将其与几种现代JS框架(例如React或Vue)一起使用 ,甚至已经移植到其他几种语言 。 If you’re looking for a challenge, why not try extending the employee directory to add the missing CRUD functionality. And if you get stuck with the syntax, don’t forget that help is always at hand. 如果您正在寻找挑战,为什么不尝试扩展员工目录以添加缺少的CRUD功能。 而且,如果您对语法感到困惑,请不要忘记总是有帮助 。 翻译自: https://www.sitepoint.com/a-beginners-guide-to-pug/nav#navbar-default
.container-fluid
h1.navbar-header My Website!
ul
li
a(href='/') Home
li
a(href='/page-1') Page 1
li
a(href='/page-2') Page 2
input.search(
type='text'
name='search'
placeholder='Enter a search term...'
)
纯文本和文本块 (Plain Text and Text Blocks)
h1.navbar-header My Website! We can write anything we want here …
|
):|
)为行添加前缀: p
| You are logged in as
| [email protected]
.
right after the tag name, or after the closing parenthesis, if the tag has attributes:.
如果标签具有属性,则紧接在标签名称之后,或在右括号之后。 p.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.
注释 (Comments)
// My wonderful navbar
nav#navbar-default
//- My wonderful navbar
nav#navbar-default
nav#navbar-default // My wonderful navbar
//
My wonderful navbar
It is just so, awesome!
nav#navbar-default
基本语法演示 (Basic Syntax Demo)
在帕格中使用JavaScript (Using JavaScript in Pug)
缓冲与非缓冲代码 (Buffered vs Unbuffered Code)
-
). It doesn’t directly add anything to the output, but its values may be used from within Pug:-
)开头。 它不会直接在输出中添加任何内容,但是可以在Pug中使用其值: - const name = "Jim"
//- Now I can refer to a 'name' variable in my Pug code
=
). It evaluates a JavaScript expression and outputs the result.=
)开头。 它评估一个JavaScript表达式并输出结果。 p= 'Two to the power of ten is: ' + 2**10
p= ''
插补 (Interpolation)
#{}
. Here, Pug will evaluate any code between the curly brackets, escape it, and render it into the template.#{}
。 在这里,Pug将评估大括号之间的所有代码,对其进行转义,并将其渲染到模板中。 - const name = "jim"
p Hi #{name}
- const name = "jim"
- //- Upcase first letter
p Hi #{name.charAt(0).toUpperCase() + name.slice(1)}
!{}
. But this is not the best idea if the input comes from an untrusted source.!{}
将未转义的值呈现到模板中。 但是,如果输入来自不受信任的来源,那么这不是最好的主意。 #{}
. For example: img(alt=name)
.#{}
。 例如: img(alt=name)
。 迭代 (Iteration)
each
keyword makes it easy to iterate over arrays:each
关键字使遍历数组变得容易: - const employees = ['Angela', 'Jim', 'Nilson', 'Simone']
ul
each employee in employees
li= employee
-
const employee = {
'First Name': 'James',
'Last Name': 'Hibbard'
}
ul
each value, key in employee
li= `${key}: ${value}`
- const employees = []
ul
each employee in employees
li= employee
else
li The company doesn't have any employees. Maybe hire some?
for
as an alias for each
.for
为的别名each
。 有条件的 (Conditionals)
-
const employee = {
firstName: 'James',
lastName: 'Hibbard',
extn: '12345'
}
#employee
p= `${employee.firstName} ${employee.lastName}`
p Extension:
if employee.extn
=employee.extn
else
| n/a
employee
object has an extn
property, then either outputting the value of that property (if it exists), or the text “n/a”.employee
对象是否具有extn
属性,然后输出该属性的值(如果存在)或文本“ n / a”。 Pug演示中JavaScript (JavaScript in Pug Demo)
sitePointEmployees
array.sitePointEmployees
数组中添加更多对象。 动手实例 (A Hands-on Example)
mkdir pug-express
cd pug-express
npm init -y
npm i express
app.js
file in the pug-express
folder:pug-express
文件夹中创建一个app.js
文件: touch app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(3000, () => {
console.log('Listening on port 3000...');
});
/
), which will respond to a GET request with the text “Hello, World!” We can test this in our browsers, by starting the server with node app.js
and then visiting http://localhost:3000./
),它将以文本“ Hello,World!”响应GET请求。 我们可以在浏览器中对此进行测试,方法是使用node app.js
启动服务器,然后访问http:// localhost:3000 。 添加一些数据 (Adding Some Data)
db.json
file which it will turn into a REST API that we can perform CRUD operations against.db.json
文件,该文件将转换为REST API,我们可以对其执行CRUD操作。 npm i -g json-server
db.json
file in the project’s root:db.json
文件: touch db.json
https://randomuser.me/api/?results=25
and copy the results into db.json
.https://randomuser.me/api/?results=25
然后将结果复制到db.json
。 json-server --watch db.json -p=3001
将Pug设置为模板引擎 (Setting up Pug as the Template Engine)
npm i pug
app.js
we need to tell Express to use Pug:app.js
我们需要告诉Express使用Pug: app.set('view engine', 'pug');
views
directory, then in the views
directory, add an index.pug
file:views
目录,然后在views
目录中添加一个index.pug
文件: mkdir views
touch views/index.pug
doctype html
html(lang='en')
head
title Hello, World!
body
h1 Hello, World!
app.js
like so:app.js
: const express = require('express');
const app = express();
app.set('view engine', 'pug');
app.get('/', (req, res) => {
res.render('index');
});
app.listen(3000, () => {
console.log('Listening on port 3000...');
});
建立员工目录 (Building the Staff Directory)
npm i axios
app.js
like so:app.js
: const express = require('express');
const axios = require('axios');
const app = express();
app.set('view engine', 'pug');
app.get('/', async (req, res) => {
const query = await axios.get('http://localhost:3001/results');
res.render('index', { employees: query.data });
});
app.listen(3000, () => {
console.log('Listening on port 3000...');
});
app.js
. If this starts to get annoying, check out nodemon, which will do this for you.app.js
时,都必须重新启动Node服务器。 如果这变得令人讨厌,请查看nodemon ,它将为您完成此操作。 index.pug
to look like the following:index.pug
更改为如下所示: doctype html
html(lang='en')
head
title Staff Directory
link(rel='stylesheet' href='https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css')
style.
table.ui.celled img { display: inline-block; }
footer { margin: 35px 0 15px 0; text-align: center }
body
main#main
h1.ui.center.aligned.header Staff Directory
.ui.container
table.ui.celled.table.center.aligned
thead
tr
th Avatar
th First Name
th Last Name
th Email
th Phone
th City
tbody
each employee in employees
tr
td
img.ui.mini.rounded.image(src=employee.picture.thumbnail)
td #{employee.name.first}
td #{employee.name.last}
td #{employee.email}
td #{employee.phone}
td #{employee.location.city}
tfoot
tr
th(colspan='6')
footer
p © #{new Date().getFullYear()} My Company
employees
that we are passing in from app.js
and outputting their details to a table.app.js
传入的employees
数组,并将其详细信息输出到表中。 模板继承 (Template Inheritance)
layout.pug
file in the views
directory:views
目录中创建layout.pug
文件开始: touch views/layout.pug
doctype html
html
head
title Staff Directory
link(rel='stylesheet' href='https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css')
style.
table.ui.celled img { display: inline-block; }
footer { margin: 35px 0 15px 0; text-align: center }
body
main#main
h1.ui.center.aligned.header Staff Directory
.ui.container
block content
block footer
footer
p © #{new Date().getFullYear()} My Company
block content
and block footer
) that a child template may replace. In the case of the footer
block, we’ve also defined some fallback content that will be rendered if the child template doesn’t redefine this block.block content
和block footer
),它们可以替换子模板。 对于footer
块,我们还定义了一些后备内容,如果子模板未重新定义此块,则将呈现这些内容。 index.pug
file to inherit from our layout:index.pug
文件从我们的布局继承: extends layout.pug
block content
table.ui.celled.table.center.aligned
thead
tr
th Avatar
th First Name
th Last Name
th Email
th Phone
th City
tbody
each employee in employees
tr
td
img.ui.mini.rounded.image(src=employee.picture.thumbnail)
td #{employee.name.first}
td #{employee.name.last}
td #{employee.email}
td #{employee.phone}
td #{employee.location.city}
tfoot
tr
th(colspan='6')
混合蛋白 (Mixins)
mixins
in the views
folder and in that folder create a file named _tableRow.pug
:views
文件夹中创建一个名为mixins
的文件夹,然后在该文件夹中创建一个名为_tableRow.pug
的文件: mkdir views/mixins
touch views/mixins/_tableRow.pug
mixin
keyword. They are compiled to functions and can take arguments. Add the following to views/mixins/_tableRow.pug
:mixin
关键字声明mixin
。 它们被编译为函数并且可以接受参数。 将以下内容添加到views/mixins/_tableRow.pug
: mixin tableRow(employee)
tr
td
img.ui.mini.rounded.image(src=employee.picture.thumbnail)
td #{employee.name.first}
td #{employee.name.last}
td #{employee.email}
td #{employee.phone}
td #{employee.location.city}
index.pug
like so:index.pug
: extends layout.pug
include mixins/_tableRow
block content
table.ui.celled.table.center.aligned
thead
tr
th Avatar
th First Name
th Last Name
th Email
th Phone
th City
tbody
each employee in employees
+tableRow(employee)
tfoot
tr
th(colspan='6')
employee
object to display.employee
对象以进行显示。 结论 (Conclusion)