无论是在服务器端还是在客户端,模板都能被编译成HTML。
4.1 Jade的语法和特性
Jade借鉴了Haml的很多地方,所以语法上和Haml比较相近。
标签:为HTML元素同时渲染闭合和开始标签。
变量/数据:传给Jade模板的数据称为locals。
h1 = title
p = body
(locals):
{
title: "Express.js Guide",
body: "The Comprehensive Book on Express.js"
}
属性:紧跟在标签的名字之后,用括号括起来,格式是name=value。
div(id="content", class="main")
a(href="http://xxx.com", title="XXX") XXX
form(action="/login")
button(type="submit", value="save")
div(class="hero-unit") Lean Node.js!
字面量:#content
文本:通过符号|可以输出原始文本
Script和Style块:写前端JavaScript
JavaScript代码:用符号-、=或!=,可注入
注释://和//-
if语句:
else语句:
过滤器:一个文本块需要用另外一种语言写时,就会用到过滤器,比如Markdown的过滤器。
读取变量:通过#{name}来实现的
case语句:when, default
函数mixin:mixin name(param, param2, ...),用法是+name(data)
include:include ./include/header
extend:
4.2 单独使用Jade
安装jade:npm install jade -save
4.3 Handlebars的语法
是一个模板引擎,不同于Jade,它不允许在模板里写很多JavaScript逻辑。这有助于保存模板的简洁和严格相关的数据表示。
要求书写完整的HTML代码。
变量:<h1>{{title}}</h1>
each语句:
<div>
{{#each language}}
<p>{{@index}}.{{this}}</p>
{{/each}}
</div>
非转义输出:
if语句:
unless:
with:当有很多个有内嵌属性的对象是,可以使用with传递上下文。
注释:<!--和-->
自定义Helpers:与Jade中的mixin相似。
Include:
4.4 单独使用Handlebars
$ npm install handlebars --save
4.5 Express.js 4中Jade和Handlebars的用法
默认情况下,Express.js 4.x和3.x可以使用提供给res.render方法的模板扩展,也可以使用通过view engine设置的默认扩展,去调用模板库里的require方法和__express方法。换句话说,Express.js是在外部实例化模板引擎库的,该库需要有_express方法。
4.6 项目:给博客添加Jade模板
layout.jade:整个app用的全局模板
doctype html
html
head
title = appTitle
<!-- 前端公共资源 -->
script(type="text/javascript", src="js/jquery-2.0.3.min.js")
link(rel="stylesheet", href="/css/bootstrap-3.0.2/css/bootstrap.min.css")
link(rel="stylesheet", href="/css/bootstrap-3.0.2/css/bootstrap-theme.min.css")
link(rel="stylesheet", href="/css/style.css")
script(type="text/javascript", src="/css/bootstrap-3.0.2/js/bootstrap.min.js")
script(type="text/javascript", src="/js/blog.js")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
body
#wrap
//<!-- 样式 -->
.container
h1.page-header = appTitle
p.lead Welcome to example from Express.js Experience by
a(href="http://twitter.com/azat_co") @azat_co
|. Please enjoy.
block page
block header
div
//<!-- 菜单 -->
include includes/menu
//<!-- 为用户展现信息 -->
block alert
div.alert.alert-warning.hidden
.content
//<!-- 主要内容 -->
block content
block footer
footer
.container
p
| Copyright © 2014 | Issues? Submit to
a(href="https://github.com/azat-co/blog-express/issues") GitHub
| .
index.jade:显示博客列表的主页
extends layout
block page
- var menu = 'index'
block content
if (articles.length === 0)
| There's no published content yet.
a(href="/login") Log in
| to post and publish.
else
each article, index in articles
div
h2
a(href="articles/#{article.slug}") = article.title
article.jade:单篇文章的页面
extends layout
block content
p
h1 = title
p = text
login.jade:显示登录表单的页面
extends layout
block page
- var menu = 'login'
block content
.col-md-4 .col-md-offset-4
h2 Log in
div = error
div
form(action="/login", method="POST")
p
input.form-control(name="email", type="text", placeholder="hi@azat.co")
p
input.form-control(name="password", type="password", placeholder="***")'
p
button.btn.btn-lg.btn-primary.btn-block(type="submit") Log in
post.jade:增加一篇新文章的页面
extends layout
block page
- var menu = 'post'
block content
h2 Post an Article
div = error
div.col-md-8
form(action="/post", method="POST", role="form")
div.form-group
label(for="title") Title
input#title.form-control(name="title", type="text", placeholder="JavaScript is good")
div.form-group
label(for="slug") Slug
input#slug.form-control(name="slug", type="text", placeholder="js-good")
span.help-block This string will be used in the URL
div.form-group
label(for="text") Text
textarea#text.form-control(rows="5", name="text", placeholder="Text")
p
button.btn.btn-primary(type="submit") Save
admin.jade:登录后管理文章的页面
extends layout
block page
- var menu = 'admin'
block content
div.admin
if (articles.length === 0)
p
| Nothing to display. Add a new
a(href="/post") article
|.
else
table.table.table-stripped
thead
tr
th(colspan="2") Actions
th Post Title
tbody
each article, index in articles
tr(data-id="#{article._id}", class=(!article.published)?'unpublished':'')
td.action
button.btn.btn-danger.btn-sm.remove(type="button")
span.glyphicon.glyphicon-remove(title="Remove")
td.action
button.btn.btn-default.btn-sm.publish(type="button")
span.glyphicon(class=(article.published)?"glyphicon-pause":"glyphicon-play",title=(article.published)?"Unpublish":"Publish")
td = article.title
script(type="text/javascript", src="js/admin.js")