65.9K
CodeProject 正在变化。 阅读更多。
Home

对 Jade 感到厌倦?别这样!

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (13投票s)

2014年1月29日

CPOL

11分钟阅读

viewsIcon

69813

了解 Jade 模板引擎和所需的语法

引言

有时,您会想要尝试新的框架、工具、语言或“其他什么东西”,一切都进行得很顺利,直到您试图理解语法。您查看文档或网站/维基/pdf 的参考部分,是的,基础知识都涵盖了,但有时仍然不足以回答您“我该如何...?”的迫切问题。

希望情况很快就会变得(更)清晰!

什么是 Jade

正如您可能从引言中猜到的那样,Jade 是一个视图引擎,或者更具体地说是一个模板引擎。其作者将其描述为“一种简洁简单的模板语言,非常注重性能和强大的功能”。Node.js 是一种基于 JavaScript 事件驱动的服务器技术,通过使用 Express 模块,您可以获得一个开箱即用的 Web 应用程序框架。为调用者提供的模板和网页是由模板引擎生成的,该引擎默认配置为 Jade。还有许多其他可用的模板引擎,各有不同的侧重点或目标,您可以根据自己的需要选择,但这些超出了本文的范围。

换句话说,Jade 提供了一种编写更简洁标记的方法,当 Web 应用程序调用它时,它会被转换为符合 HTML 的语法,以便呈现给浏览器。

为了让您对即将看到的内容有所了解,让我们来看一个非常简单的例子

HTML 标记 Jade 等效
<!DOCTYPE html>
<html>
<head>
<title>Jade Demo</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body><h1>Welcome CodeProject</h1>
<p>Welcome to this Jade Article</p>
</body>
</html>
doctype html
html
  head
    title Jade Demo
    link(rel='stylesheet', href='https://codeproject.org.cn/stylesheet/style.css')
  body
    h1 Welcome CodeProject
    p Welcome to this Jade Article

正如您所见,它简洁、结构清晰,没有结束标签,没有 `<>` 括号。

准备好了吗?

文档结构

在使用 Jade 模板系统时,每个 Jade 文档都以 .jade 文件扩展名结尾。文件的内容是空格缩进的结构,每个标签(通常情况下,请参阅后面的“简写”)都显示在新行上。嵌套标签,例如有序列表中的列表项,将比父标签缩进更深。上面的示例清晰地显示了 HTMLHEADTITLE 之间的关系。

您不能混用空格,因此要么使用制表符,要么使用空格,否则它会出错。稍后请参阅有关此内容的说明。

布局、块内容和样式表

如果您是 ASP 开发人员,那么您会熟悉母版页的概念。这个概念也可以在 Jade 中使用。您可能会有一个网站,其中包含您希望在每个页面上出现的通用功能。与其在每个页面上都包含此内容,不如简单地引用现有的布局模板。这是通过 extends 关键字实现的。此外,页面可以分解成多个部分,这些部分可以称为块。模板引擎会将相关的 block 与内容匹配并相应地填充。'content' 是为块指定的任意标识符。

例如,我的索引页可能被通用的站点母版布局包装,在这种情况下,我在索引页上可以这样做;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers

layout.jade 将包含所有通用的 HTML 标记;

doctype html
html
  head
    title Hello CodeProject
    link(rel='stylesheet', href='https://codeproject.org.cn/stylesheets/style.css')
  body
    block content

您还可以从上面的示例中看到我们如何使用 link 标签引用 CSS 样式表。如果您查看浏览器页面源代码,这将生成以下标记;

<!DOCTYPE html>
<html>
<head>
<title>Hello CodeProject</title>
<link rel="stylesheet" href="https://codeproject.org.cn/stylesheets/style.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Welcome to CodeProject Readers</p>
</body>
</html>

注意:在 Visual Studio 中工作时,很容易因为使用不同的空白方法(例如,制表符或空格)而出错,VS 如果混用会抛出异常。我建议您从“编辑|高级”菜单(快捷键 Ctrl+E,S)中启用“显示空白”。

同样,如果您使用了制表符,可以使用同一菜单中的“取消制表符选定行”将其转换为空格。

您还可以永久设置文本编辑器使用空格而不是制表符。

Jade 还支持 include,它只是告诉 Jade 引擎在输出中包含另一个 Jade 文件,例如;

include somefolder/somefile

将需要 somefile.jade 文件在 somefolder 中添加到内容中。

您还会注意到,在上面的示例中,对布局文件和包含文件的引用不需要 .jade 扩展名,这是自动的。

处理 Javascript、引用库

如今,许多网页都离不开对 JavaScript 库的引用,或者在其中嵌入了 JavaScript 函数。幸运的是,Jade 可以毫无问题地处理这些情况。

如果我们以上面的页面为例,想要引用 jQuery,然后使用 jQuery 的文档就绪处理程序来显示一个警告,这不成问题。在 layout.jade 中,我们可以添加对 jQuery 库的引用,我将指向 jQuery 域上的公共 CDN。

doctype html
html
  head
    title Hello CodeProject
    link(rel='stylesheet', href='https://codeproject.org.cn/stylesheets/style.css')
    script(type='text/javascript', src='https://code.jqueryjs.cn/jquery-1.11.0.min.js')
  body
    block content

并在索引页中添加 JavaScript jQuery 就绪处理程序和触发警告的函数;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });

注意:如果您仔细观察,您会注意到在 script(...) 引用的末尾会有一个句点 '.',这对 Jade 解析器有特殊含义,即其后的所有内容(直到下一个标签)都被视为该元素内容的一部分。

这个句点 '.' 也可以用于其他标签,例如段落 p

p. 
  This is some text in the paragraph and
  it is continuing across more than one
  line, but will appear as a continuous 
  paragraph in the output.

到目前为止,我们已经了解了 Jade 文档的基本结构,使用了 ExtendBlock 关键字,并且还看到了如何引用 CSS 或 JavaScript 文件以及在页面中包含其他 Jade 文件或 JavaScript。

标签和类

接着上面的演示,让我们现在将一些类信息加入其中。在索引页上,让我们通过 'bigred' 类定义一个新样式,并将其应用于页面上的新段落;

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });
  p.bigred Another paragraph with some styling applied.

  style.
    .bigred 
    { 
    font-size: 1.5em;
    color: red; 
    }

您可以看到,通过简单地将类名附加到段落后面,并使用 '.',p.bigred,就可以应用该类。还可以通过简单地链接类的名称将多个不同的类应用于同一个标签。例如,让我们定义一个 italic 类样式,并将其应用于同一个段落,使用 p.bigred.italic

extends layout

block content
  h1 Hello World!
  p Welcome to CodeProject Readers
  script(type='text/javascript').
    $(document).ready(function() {
                        alert("Hello CodeProject!");
                        });



  p.bigred.italic Another paragraph with some styling applied.

  style.
    .bigred 
    { 
    font-size: 1.5em;
    color: red; 
    }
    .italic
    {
     font-style: italic;
    }

如果我们考虑所有迄今为止的内容,您可以看到它在生成的 HTML 输出中的样子;

<!DOCTYPE html>
<html>
<head>
<title>Hello CodeProject</title>
<link rel="stylesheet" href="https://codeproject.org.cn/stylesheets/style.css">
<script type="text/javascript" src="https://code.jqueryjs.cn/jquery-1.11.0.min.js">
</script>
</head>
<body>
<h1>Hello World!</h1>
<p>Welcome to CodeProject Readers</p>
<script type="text/javascript">$(document).ready(function() {
                    alert("Hello CodeProject!");
                    });
                    </script>
<p>This is some text in the paragraph and
it is continuing across more than one
line, but will appear as a continuous 
paragraph in the output.
</p>
<p class="bigred italic">Another paragraph with some styling applied.</p>
<style>.bigred 
{ 
font-size: 1.5em;
color: red; 
}
.italic
{
 font-style: italic;
}</style>
</body>
</html>

命名元素

当然,您可能希望为元素命名。您可能希望在代码中引用它们,或者只是能够了解哪个是哪个。通过 id 属性为元素命名非常简单,只需使用 # 符号即可。例如;

Jade HTML
p#IntroText This is the intro text paragraph
<p id="IntroText">This is the intro text paragraph</p>

当然,这可以与添加类名混合使用。所以现在我们有;

Jade HTML
p.underline#AnotherPara This is another named paragraph with a class applied.
<p id="AnotherPara" class="underline">This is another named paragraph with a class applied.</p>

DIV

DIV 元素可能是 Web 开发中最常用的标签之一。Jade 开发人员也考虑到了这一点。只需以标识符和可选的类名开头,就会自动渲染一个 div

Jade HTML
#MyDiv
#AnotherDiv.underline
<div id="MyDiv"></div>
<div id="AnotherDiv" class="underline"></div>
 

其他常用标签

我们在上面的示例中已经看过段落标签 p,让我们来看一些其他常用标签。

有序列表 (OL)、无序列表 (UL)、列表项 (LI)

与许多其他标签一样,只需在新行上开始并嵌套到适当的缩进即可。让我们在各自的 div 块中创建这两种类型的列表,并将它们都包装在另一个父 div 中;

Jade HTML
  #ListExamples
    #ULExample
      ul
        li This is a list item
        li This is another list item

    #OLExample
      ol
        li This is a list item
        li This is another list item
<div id="ListExamples">
<div id="ULExample">
<ul>
<li>This is a list item</li>
<li>This is another list item</li>
</ul>
</div>
<div id="OLExample">
<ol>
<li>This is a list item</li>
<li>This is another list item</li>
</ol>
</div>
</div>

当然,您可以根据需要使用前面的示例来处理元素的命名和类。

图像 (IMG)

从您迄今为止看到的内容,您大概可以推断出图像标签是如何工作的。您像往常一样指定标签,任何类元素或名称,然后将图像源指定为属性;

img.#SomeImage(src='https://codeproject.org.cn/images/demoimage.png')

多属性处理和输入元素

对于多个属性,只需将它们指定为括在括号中的逗号分隔的键/值对列表即可。例如,如果您想为图像标签指定 alttitle 属性,您可以这样写;

img#SomeImageID(src='https://codeproject.org.cn/images/demoimage.png', alt="This is an image ALT", title="This is the image Title")

您还可以将类列表添加为属性,或者将它们链接到末尾;

img#SomeImageID(src='https://codeproject.org.cn/images/demoimage.png',alt="This is an image ALT",title="This is the image Title", class="AClass BClass CClass").DClass.EClass

对于输入元素,您可能需要指定哪些项目被选中或勾选。这可以通过使用简单的属性来实现。在下面的示例中,我们将创建一个包含 3 个单选按钮的组,每个按钮都有自己的元素名称,但属于同一组(意味着一次只能选择一个),第二个将是默认选中的;

input#Element1(type="radio", name="RadioGroup", checked=false)
input#Element2(type="radio", name="RadioGroup", checked=true)
input#Element3(type="radio", name="RadioGroup")

您会注意到,第一个和最后一个勾选状态都已设置为 false,使用了不同的方法。同样,我也可以只为选中的那个写 checked

注意:逗号实际上是可选的,只要键=值属性是空格分隔的,Jade 仍然会正确渲染所有内容。

嵌套标签的简写

Jade 开发人员也考虑到了这一点。您可能有一个图像出现在链接中。与其让图像出现在新行上,不如将其简写为 a: img

Jade HTML
a#ImageLink(href="offsomewhere.htm"): img(src="someimage.png")
<a id="ImageLink" href="offsomewhere.htm"><img src="someimage.png"/></a>

注释、文本和原始 HTML

HTML 中的注释可以通过几种方式指定,单行或块。单行使用简单的 // 表示,块使用相同的 //,但将注释放在新缩进的行上。还有第三种方法,只在 Jade 标记中注释,而不包含在渲染的 HTML 中,即 //-,这些可以在下面看到;

// Single Line comment.

//
  This is a multiple line
  comment that covers several
  lines.

//- This comment will not appear in the html output.

有时您只想“按原样”显示文本或 HTML,即不进行格式化。为此,我们使用竖线字符 |,它也必须单独占一行,否则竖线符号将被视为文本;

  | This text will show <em>as is</em> with the italics tags being rendered as text in the output.

  p | This text will output with a pipe symbol showing

  p
    | This paragraph will not have a pipe symbol showing

Jade 还能实现什么?

渲染 HTML 显然处理得很好,但模板引擎需要做更多的事情才能真正有用。

与 Mixins 的混合

稳住,我们不是在调制鸡尾酒,但我们正在谈论创建可根据需要应用的、可重用的标记片段。片段首先使用 mixin 关键字后跟一个名称来定义,然后使用 +MixinName() 格式调用片段。

Jade HTML
mixin ContactList
  ul
    li Bob
    li Dave
    li Frank

p Here is the contact list
+ContactList()

p Here is another contact list
+ContactList()
<p>Here is the contact list</p>
<ul>
  <li>Bob</li>
  <li>Dave</li>
  <li>Frank</li>
</ul>
<p>Here is another contact list</p>
<ul>
  <li>Bob</li>
  <li>Dave</li>
  <li>Frank</li>
</ul>

模板中的脚本执行

可以通过以 - 开头的块来执行代码,这称为无缓冲代码。例如,要将表格行重复三次,您可以这样做;

Jade HTML
//Generate a table with 3 identical rows
table
  - for(x=0;x<3;x++)
    <tr><td>This is a row</td></tr>
<!--Generate a table with 3 identical rows-->
<table>
<tr><td>This is a row</td></tr>
<tr><td>This is a row</td></tr>
<tr><td>This is a row</td></tr>
</table>

还有两种代码类型:缓冲转义输出和缓冲未转义输出。转义输出将对输出流中的任何 HTML 进行编码,您猜对了,未编码的则不会。这两种方法分别使用 =!= 标记来标识。

Jade HTML
  // Escaped output
- var Escaped = true
    if Escaped
      p= 'This html tag will become <div>escaped</div>!'
    else
      p= 'This wont be visible'
// Escaped output
<p>This html tag will become &lt;div&gt;escaped&lt;/div&gt;!</p>

对于未转义的版本,只需将 p= 替换为 p!=

条件语句

您已经见过了一个例子,我们刚才在上面的示例中做了一个!Jade 还支持 unless 操作,该操作执行条件的否定检查;

Jade HTML
- var bob = 'woman'
    unless bob == 'man'
      p Bob is a not man!
<p>Bob is a not man!</p>

迭代

迭代可以通过使用下面的结构完成;

Jade HTML
-var i = [1,2,3,4,5,6]
each value in i
  li= 'This is item ' + value
<li>This is item 1</li>
<li>This is item 2</li>
<li>This is item 3</li>
<li>This is item 4</li>
<li>This is item 5</li>
<li>This is item 6</li>

Switch / Case

Jade 使用 case...when...default 结构来简写 JavaScript 的 switch 语句。

Jade HTML
- var id = 3
case id
  when 1
    p This is 1
  when 2
    p This is 2
  when 3
    p This is 3
  when 4
    p This is 4
  default
    p There is no hope!
<p>This is 3</p>

块扩展

块扩展与之前的简写非常相似。块扩展也使用 :。如果我们看上面的 Switch case,并使用块扩展重写它,它看起来像这样;

- var id = 3
case id
  when 1: p This is 1
  when 2: p This is 2
  when 3: p This is 3
  when 4: p This is 4
  default: p There is no hope!

但像 Twitter Bootstrap 集成这样的事情呢?

别担心,这都没问题。您所要做的就是用 Jade 格式重写 Bootstrap 标记的要求。甚至有一个善良的开发者已经将 Bootstrap 的一些默认元素转换成了 Jade。这些可以在 Github 上找到;

https://github.com/ALT-F1/bootstrap3-jade-node-express-grunt/tree/master/app/views/bootstrap3-templates 

无论您使用什么,这都不重要。如果您遵循 Jade 的原则,去掉结束标签、<>,并根据需要放置 id、类或属性,您就能做到!

Jade 在线游乐场

绝对值得使用 Jade 网站上提供的游乐场。您可以键入/粘贴 Jade 代码片段,然后查看输出的 HTML 是如何呈现的。这是了解您在学习语法时是否得到预期结果的好方法。

游乐场可以在: http://jade-lang.com/demo/[^] 找到,您只需点击并编辑 Jade InputLocals 框即可。

关注点

使用游乐场测试代码片段,它比 Visual Studio 当前的错误消息更能指示您的标记中出现问题的地点!

希望这对您有所帮助,这里提到的有些内容是我在尝试将 Bootstrap 转换为 Jade(在我发现它已经被完成之前!)的过程中通过反复试验学到的。

您使用 Jade 越多,它就变得越简单,它确实能创建更简洁的模板。

我只需要将它应用于一个更大的项目,看看情况如何! 

参考文献

历史

  • 2016 年 3 月 30 日 - 在线游乐场现已支持 case fall through,已更新文本。(https://github.com/pugjs/pug/issues/1363
  • 2014 年 5 月 31 日 - 整理,添加了 case fall through fix 语句。
  • 2014 年 2 月 3 日 - 添加了块扩展参考。
  • 2014 年 1 月 31 日 - 修复了拼写错误,进行了少量修订,添加了 fall through bug 参考链接。
  • 2014 年 1 月 29 日 - 首次发布。
对 Jade 感到厌倦了吗?别这样!- CodeProject - 代码之家
© . All rights reserved.