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=" ...
随机推荐
- 在.NET中调用Java的类
.NET不能直接调用Java的类,但IKVM.NET解决了这个问题. IKVM.NET提供了两种方式调用java的类: ①把生成的jar包放置在程序根目录,然后通过创建URL实例的方式去调用类中的方法 ...
- 使用Python的http.server实现一个简易的Web Api对外提供HanLP拼音转换服务
由于采集省市区镇数据需要对地名进行拼音转换,由于第三方高准确度接口对IP进行了限制,处理大量数据变得异常缓慢. 使用了一个折中的办法,省市区 3级(3千+)用高准确度接口(几乎没有拼错的地名),镇级( ...
- 面试 15:顺时针从外往里打印数字(剑指 Offer 第 20 题)
面试 15:顺时针从外往里打印数字 题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印每一个数字.例如输入: {{1,2,3}, {4,5,6}, {7,8,9}} 则依次打印数字为 1.2.3. ...
- React中嵌套组件与被嵌套组件的通信
前言 在React项目的开发中经常会遇到这样一个场景:嵌套组件与被嵌套组件的通信. 比如Tab组件啊,或者下拉框组件. 场景 这里应用一个最简单的Tab组件来呈现这个场景. import React, ...
- python2中reload(sys)后设置编码
python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't deco ...
- 抽象代数-p22商群
G/e={g{e}|g∈G}={{g}|g∈G}=G G/G={gG|g∈G}={G} (gG=G左乘g是G上的双射,它的逆映射是左乘g^-1) 所以 G/G 只有一个元素,所有G 就只能是 ...
- java集合迭代器
一.Java中有一个设计模式是迭代器模式 1.迭代器模式定义迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 2.迭代器模式概述Java集合框 ...
- PropertyChangeSupport 监听器模式的应用
PropertyChangeSupport 类实现的监听器功能 ,它是java jdk自带的一个类,用于监听某个对象属性的改变来触发相应信息,具体看代码介绍 import java.beans.Pro ...
- Highgo 瀚高数据库的简单搭建以及处理参数等.
1. 获取一个瀚高数据库的安装文件 我这边只获取了 瀚高的 2.0.4 的windows x64 版本的. 来源: 同事从供应商那里获取的. 2. windows上面简单安装 很简单 exe 一路ne ...
- vue.js 添加 fastclick的支持
fastclick:处理移动端click事件300毫秒延迟 1.兼容性 iOS 3及更高版本的移动Safari iOS 5及更高版本的Chrome Android上的Chrome(ICS) Opera ...