Express学习 ------模版引擎(handlebars)
Handlebars一款js模版引擎,我们在做客户端开发的时候,也可能已经使用过。它语法比较简单,和我们平常写的html 一样,只不过html 中可以加入handlebars 表达式。 handlebars表达式用 {{variable}} 表示,当程序运行的时候,变量就被传进来的数据代替。下面就是一个比较简单的模版:
<header>
<h2>{{title}}</h2>
<p>{{content}}</p>
</header>
当我们传递一个对象数据(如下)给这个模板的时候,
<script>
var context = {
title:"My New Post",
content: "This is first post"
}
</script>
它就会被解析为
<header>
<h2>My New Post</h2>
<p>This is first post</p>
</header>
非常简单,除了几个表达式,就是html 代码,当然,这也展示的它的特点,模板和数据分开,只定义视图,即需要展示给用户看的部分。
Express 默认不支持Handlebars 模板,但我们可以通过 安装express-handlebars 第三方插件来进行支持,创建一个项目来体验一下 express和 handlebar.
新建express 文件夹,npm init -y 快速建立 package.json 文件,安装 express 和 express-handlebars(npm install express express-handlebars -S). 再新建 server.js 作为项目的启动文件,views 文件夹作为 模版存放的地方,下面再建两个文件夹 layouts 和partials, 这两个文件夹的作用后面再说,先放这里。 目录如下:

首先用express 搭建http 服务器(如下),在当前文件夹中调用cmd命令窗口,输入node server, 然后在浏览器地址栏中输入localhost:8080, 可以看到hello world ,表明服务器搭建成功
var express = require('express'),
app = express();
app.use(function (req,res) {
res.send("hello world")
})
app.listen(8080);
由于 express 不支持Handlebars 模板,我们先要注册该模板引擎,调用app.engine() 方法来进行,express-handlebar 提供了两种方式来注册handlebars ,简单的看一下express-handlebars 里面 index.js 的源码
var ExpressHandlebars = require('./lib/express-handlebars');
exports = module.exports = exphbs;
exports.create = create;
exports.ExpressHandlebars = ExpressHandlebars;
// -----------------------------------------------------------------------------
function exphbs(config) {
return create(config).engine;
}
function create(config) {
return new ExpressHandlebars(config);
}
在项目中使用express-handlebars, 就需要引入它。 server.js 中 var exphbs =require('express-handlebars'); 引入它。当我们引入时,node 就会从node_module 中查找我们安装的模块,如果是一个文件夹,node 就会去查找该文件夹下的 index.js文件。我们看一下node_modules, express-handlebars 是一个文件夹,打开文件夹,可以看到index.js, 就是上面的源码,可以看到它暴露出了 exphbs 函数,我们的定义的变量exphbs 就是指向这个函数,它还可以接受一个配置参数。我们可以调用这个函数进行配置
var express = require('express'),
app = express();
// 引入express-handlebars
var exphbs = require("express-handlebars")
app.engine("handlebars", exphbs({
defaultLayout: "main"
}))
app.listen(8080);
app.engine 接受两个参数,一个是名字,这很好理解,注册肯定要给它起个名字,以便后面使用。第二个是函数,必须符合express 注册模版的规范,我们按照这个模式写,就可以了。它有好多配置选项,这只写了一个。
我们看到它还有一个create 方法,我们也可以用这种方式进行配置
app.engine('handlebars', exphbs.create({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials']
}).engine)
上面这种写法,可能写的不太好理解,我们把它拆分一下, 又增加了两个配置项
var hbs = exphbs.create({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials']
});
app.engine('handlebars', hbs.engine);
不管用哪种方法,我们都成功注册了handlebars模版,现在我们要告诉express来使用 handlerbars, 调用app.set 方法, 第二个参数是我们注册的模板的名字,就是app.engine中第一个参数,他们要保证一致
app.set(“view engine”, 'handlebars' )
最后还要告诉express 我们的模版文件放在什么地方,以便express 去查找使用,还是要调用app.set() 方法
app.set("views", __dirname+ "/views"); // 第一个参数views是复数,一定不忘记后面的还有一个s, 要不然会报 View is not a construction
现在我们可以使用handlebar 模版引擎了,再来看一个注册模版擎时的参数 defaultLayout, layoutDir,partialsDir。default Layout, 默认布局, layout directory, 布局文件所在的目录,partial directory
局部文件所在的目录。 根据字面意思,我们也可以得到 defaultLayout: 设置默认布局文件,layoutDir 设置布局文件所在的位置,partialsDir 设置局部文件所在的位置。
我们需要了解一下handlebars 中的基本概念 : 布局,局部, 还有视图。
视图(views): 就是我们定义的任何的模板片段。 app.set("views", __dirname+ "/views"), 我们已经设置我们的视图文件所放的位置,就是views文件夹下。我们在于views 文件夹下定义一个 视图,index.handlebars
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">欢迎使用handlebars</h3>
</div>
</div>
布局:也是一种模版,不过作用比较特殊,所以单独列出来。想一下我们的网站,主要分为header ,main, footer 三个部分,通常header ,footer 部分是不变的,只有main 是经常改变的, 程序在运行的过程中,只要动态的替换掉main 就可以了。这时我们就可以定义一个文件,包含不变的header, footer 和 可变的main,这个文件就是布局。在注册handlebars的时候,我们设置 defaultLayout 为main,其实是main.handlebars, 只不过是 省略了后缀名,并且设置 layoutDir( 布局文件所在的位置)为views文件夹下 layouts文件夹,那么就在 layouts文件夹新建main.handlebars 文件
<!doctype>
<html>
<head>
<title>Meadowlark Travel</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body> {{{body}}} </body>
</html>
A layout is simply a Handlebars template with a {{{body}}} placeholder. Usually it will be an HTML page wrapper into which views will be rendered. 官网也说了,布局也是模版,只不过它 带有{{{body}}} 占位符,我们的view 就会渲染在{{{body}}}占位符所在的地方。
局部文件(partial):有些时候,有几个页面要共用相同的部分,如侧边栏这,我们通常都会封装为组件,然而在handlebars 中,它们称之为局部文件partial,可以知道局部文件也是代码片段。我们在注册模版引擎的时候,设置 partialsDir(局部文件所在的路径)为views 下面的 partials文件夹,所以我们在partials文件夹下面建一个局部文件,命名为partial.handlebars
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">侧边栏</h3>
</div>
</div>
局部文件是几个页面要共用部分,它也应该包含在布局中。 在布局中,如何使用? {{> partial}} >加局部文件的名称,增加bootstrap
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Express Handlebars 使用</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" >
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-8">
{{{ body }}}
</div>
<div class="col-sm-4">
{{> partial }}
</div>
</div>
</div>
</body>
定义的视图,布局,局部文件,我们怎么使用呢?这要用到render方法,去渲染模版。render 方法是定义在res 响应对象上的,所以我们浏览器端发起一个请求,让它输出动态模版,所以我们在 server.js 中定义一个路由,
整个server.js如下
var express = require('express'),
app = express();
// 引入express-handlebars
var exphbs = require("express-handlebars")
// 设置模板存放路径
app.set("views", __dirname+ "/views")
// 注册handlebars模板引擎
var hbs = exphbs.create({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials']
});
app.engine('handlebars', hbs.engine);
// 告诉express使用handlebars模板,
// 第二个参数是我们注册的模板的名字,就是app.engine中第一个参数,他们要保证一致
app.set('view engine', 'handlebars' )
// render 渲染模板
app.get('/', function (req,res) {
res.render('index')
})
app.listen(8080);
render方法,接受一个参数,那就是要渲染的模版(视图)的名字,当exrpess 执行render 的时候,它会从views 文件夹下找到我们指定的文件,然后再找到布局文件,替换掉里面的{{{body}}},如果有partial, 它还会从particals 文件夹下找到局部文件,进行合并,形在一个完整的html文件进行输出。这也就是我们上面一系列设置默认文件夹的原因。
我们每次渲染一个视图文件时,都会结合layout 布局模版渲染, 有时我们并不需要layout布局模版,这时可以在render 方法中进行设置 layout: false
app.use(function (req,res) {
res.render('404', {
layout: false
});
})
在设置模版引擎的时候,我们只指定了一个默认的布局视图,如果我们带想使用其他视图,怎么办? 调用render 方法的时候,指定layout,当然要确保这个layout文件在layout文件夹中。
app.get('/foo', function(req, res){
res.render('foo', { layout: 'microsite' });
})
现在我们页面都是静态的,没有任何改变。现在在index.handlbars 增加一个日期,{{time}}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
<!-- 增加 time -->
欢迎使用handlebars模板 <small>{{timeFormate time}}<small>
</h3>
</div>
</div>
那么我们在渲染的时候要给time传递参数, render 方法可以接受第二个可选参数,它是一个对象, 就是我们向模版中传递的数据,对象的属性就是我们在模版中定义的表达式,如time
res.render('index' , {
time: Date.now()
})
这时我们发现,页面中显示的日期,但它是日期毫秒数,我们想把他转化成年月日的形式,这就要执行一定的逻辑操作,但是handlebars不支持在模版中使用逻辑的,这时要用到 helper 助手。它其实是一个函数,对模版中的表达式执行逻辑操作, helper 在模版中使用之前要先注册。这时有两种方法,
一种是 在注册handlebars 模版引擎的时候,直接给它配置helpers
var hbs = exphbs.create({
defaultLayout: "main",
layoutDir: app.get('views') + '/layouts',
partialsDir:[app.get('views') + '/partials'],
// 增加helpers
helpers: {
timeFormate: function (time) {
var dateTime = new Date(time)
return dateTime.getFullYear() +"年"+ (dateTime.getMonth()+1)+ "月" +
dateTime.getDay() +'日'
}
}
});
一种是在调用render 方法的时候给它配置helpers
app.get('/', function (req,res) {
res.render('index' , {
time: Date.now(),
//配置helpers
helpers : {
timeFormate: function (time) {
var dateTime = new Date(time)
return dateTime.getFullYear() +"年"+ (dateTime.getMonth()+1)+ "月" +
dateTime.getDay() +'日'
}
}
})
})
上面的第一种配置方式,可以叫做全局配置,因为它在所有的模版文件中都可以使用,下面的一种则只能在 index模版中使用,可以叫做局部配置。
定义了helpers, 我们模版中就可以使用了,使用也简单,只要在模版的表达式前面加上就可以了。
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
<!-- 增加 timeFormate helper -->
欢迎使用handlebars模板 <small>{{timeFormate time}}<small>
</h3>
</div>
</div>
express-handlebars还支持子目录, 所以如果你有大量的局部文件,可以将它 们组织在一起。例如,你有一些社交媒体局部文件,可以将它们放在views/ partials/social 目录下面, 然后使用{{> social/facebook}}、{{> social/twitter}} 等来引入它们。
Express学习 ------模版引擎(handlebars)的更多相关文章
- js模版引擎handlebars.js实用教程
js模版引擎handlebars.js实用教程 阅读本文需要了解基本的Handlebars.js概念,本文并不是Handlebars.js基础教程,而是注重于实际应用,为读者阐述使用过程中可能会遇到的 ...
- 模版引擎Handlebars和Mustache
Handlebars是一款很高效的模版引擎,提供语意化的模版语句,最大的兼容Mustache模版引擎, 提供最大的Mustache模版引擎兼容, 无需学习新语法即可使用; 下面这个是基本的模版表达式, ...
- js模版引擎handlebars.js实用教程——为什么选择Handlebars.js
返回目录 据小菜了解,对于java开发,涉及到页面展示时,比较主流的有两种解决方案: 1. struts2+vo+el表达式. 这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是: ...
- js模版引擎handlebars.js实用教程——each-基本循环使用方法
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
- js模版引擎handlebars.js实用教程——each-循环中使用this
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
- js模版引擎handlebars.js实用教程——each嵌套
<!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content="text/ ...
- js模版引擎handlebars.js实用教程——循环中使用索引
<!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content="text/ ...
- js模版引擎handlebars.js实用教程——with-进入到某个属性(进入到某个上下文环境)
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
- js模版引擎handlebars.js实用教程——with-终极this应用
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
随机推荐
- 20175329 2018-2019-3《Java程序设计》第三周学习总结
学号 20175329 2018-2019-3<Java程序设计>第三周学习总结 教材学习内容总结 第四章 第四章主要介绍JAVA中的类与对象的划分,其中有很多复杂的概念以及知识点需要花很 ...
- Vscode的python配置(macOS)
_ 1. Vscode是一款开源的跨平台编辑器.默认情况下,vscode使用的语言为英文(en),以下步骤改为中文 打开vscode工具,使用快捷键组合[Cmd+Shift+p],在搜索框中输入“co ...
- UVA10256 The Great Divide
怎么又没人写题解,那我来贡献一发好了. 题目意思很简单,平面上有两种颜色的点,问你能否求出一条直线使两种颜色的点完全分开. 首先我们考虑两个点集相离的充要条件,这两个点集的凸包必须相离.(很好证明或者 ...
- UVA10838 The Pawn Chess
UVA好题没人写系列,感觉可以稍稍练习一下面向对象编程的形式(大雾) 题意很简单,在国际象棋的棋盘中有一些兵,走到对方底线即为胜利,问最优决策下谁能获胜.并输出最小步数. 首先这里的棋盘都只有\(4\ ...
- 断路器(Curcuit Breaker)模式
在分布式环境下,特别是微服务结构的分布式系统中, 一个软件系统调用另外一个远程系统是非常普遍的.这种远程调用的被调用方可能是另外一个进程,或者是跨网路的另外一台主机, 这种远程的调用和进程的内部调用最 ...
- Python全栈开发之路 【第六篇】:Python基础之常用模块
本节内容 模块分类: 好处: 标准库: help("modules") 查看所有python自带模块列表 第三方开源模块: 自定义模块: 模块调用: import module f ...
- Minesweeper
你玩过扫雷吗?这个可爱的小游戏带有一个我们记不住名字的操作系统.游戏的目标是找到所有地雷在M x N场中的位置.游戏在一个正方形中显示一个数字,它告诉你在这个正方形附近有 多少个地雷.每个方块最多有八 ...
- (第十三周)Final Review会议
项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 Final Review会议 时间:2016.12.2 13:00——15:00 地点:冬华楼一楼大厅 会 ...
- Navicat还原出现Finished - Stopped before completion的问题
查看数据库中最大的单个文件容量 SHOW VARIABLES LIKE '%max_allowed_packet%'; 设置最大单个文件容量为10M,单次有效(新建查询---运行) SET GLO ...
- 线程中的samaphore信号量及event事件
一.信号量 samaphore: 在程序中意思为同时允许几个线程运行,比如我们去水上乐园的滑梯玩时,有四个滑梯,每一个滑梯上当没有人在中间玩滑下去时才允许上人,四个滑梯1,2,3,4,同时最多四个人, ...