原文:http://fraserxu.me/2013/09/12/Using-Handlebarsjs-with-Expressjs/

最近在用Expressjs做一个项目,前后端都用它来完成。自己之前有用过Express一段时间,但是大部分都是用它来编写Restful的API,而没有真正用它所提供的前端页面渲染功能。

所以严格意义来讲这是第一次完整的项目。开始做之后就遇到了一些需要做出决定的地方。众所周知,Express的默认模板引擎是Jade.我在之前学习Express的时候,因为它是默认的引擎,所以有接触和使用过一段时间,感觉也还行。Jade在编写页面时所提供的嵌套功能比较实用,可以节省很大的代码量。

Jade is a high performance template engine heavily influenced by Haml and implemented with JavaScript for node. For discussion join the Google Group.

上面是Jade Github所在页面的描述。可以得知它是一个注重性能,受Hamle影响,并特别针对Nodejs而编写的前端模板引擎。

我们先来看一下Jade官方页面所给的例子:

doctype 5
html(lang="en")
head
title= pageTitle
script(type='text/javascript').
if (foo) {
bar(1 + 5)
}
body
h1 Jade - node template engine
#container.col
if youAreUsingJade
p You are amazing
else
p Get on it!
p.
Jade is a terse and simple
templating language with a
strong focus on performance
and powerful features.

我们可以看到,对比原生的HTML, Jade明显的一个优势就是标签数量上的减少。很多地方只要按照约定的缩进规则编写,完全可以避免使用原生HTML时标签忘记闭合的问题。同时Jade还提供了一些用于渲染判断的条件,可以根据数据来决定显示的内容等功能。

另外Jade的遍历数据生成页面功能,配合使用Json数据时特别好用,可以很大程度上减少代码量。

而另外一个原因,也是觉大多数人使用Jade的原因,可能都跟我一样,因为是Express框架自带的模板引擎,而它的作者也是鼎鼎有名的TJ.

看了标题也许会奇怪,既然Jade出自大神之手,而且简单易用,我为什么还要去选择Handlebarsjs呢?

同样我们看下官方描述:

Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.

Mustache templates are compatible with Handlebars, so you can take a Mustache template, import it into Handlebars, and start taking advantage of the extra Handlebars features.

作为一个模板引擎,它继承于著名的Mustache模板引擎,具备了渲染页面的基础功能,并在其基础上进行拓展。

而另一个值得关注的是其作者Yehuda Katz,熟悉的朋友可能知道,他是著名JavaScript MVC框架Emberjs代码的主要贡献者之一,而且在他的影响下也成为了Emberjs的默认模板引擎。而另外,Yehuda本身也是W3C规范制定小组的成员之一,其影响也不亚于TJ.

抛开框架的背景,我们来看看实际的应用场景。工具无非好坏,顺手才是王道。评断一个东西好坏关键还是看它是否满足自己的应用需求。

在开始做现在的项目之前,我已经用Jade完成了所有的功能,而且对于代码也还比较满意。但是在提交之后问题产生了。

因为这个项目不是我一个人在做,和我一起合作的同事之前没有接触过Jade,而且另外一位负责编写样式的同事对于JavaScript的模板引擎也不是很熟悉。这样一来,由于我的原因,导致团队成员之间无法协作。首先是JS开发人员需要时间来掌握和熟悉Jade语法,而另外一个更为严重,Jade语法的特性决定了其不利于配套CSS的书写(这点通过编译之后可以解决,但是一定程度上增加了工作量)。

于是我开始思考使用Jade是否正确。这里的两个问题是我必须面对的,而项目的进度不能因为这个受到影响,于是我开始考虑选择其他的模板引擎。

前面提到Emberjs用到了Handlebarsjs,所以在选择时我很容易就想到了它。

Handlebars的官网给出了很多例子,而且上手也很容易,前后端通用,使用起来也很简单,这里就不对其使用多做介绍。

回到文章重点,因为Express并不提供对Handlerbarjs的直接支持,这样在使用时会面临一定问题。

要在Express中使用Handlerbars作为模板引擎,首先需要做出一下设置:

  1. 安装Express, Handlebars, Consolidate:

     "dependencies": {
    "express": "3.x",
    "consolidate": "0.4.0",
    "handlebars": "1.0.7"
    }
  2. 配置选择引擎:

     // Use handlebars as template engine
    app.engine("html", consolidate.handlebars);
    app.set("view engine", "html");
    app.set("views", __dirname + "/views");
  3. 注册模板:

     // Register partials
    var partials = "./views/partials/";
    fs.readdirSync(partials).forEach(function (file) {
    var source = fs.readFileSync(partials + file, "utf8"),
    partial = /(.+)\.html/.exec(file).pop();
    Handlebars.registerPartial(partial, source);
    })

这样我们就可以在项目中使用Handlerbars来渲染页面。但是这样做后,我又遇到了另外一个问题。通过以上的方法我可以很容易的单独去加载某个页面。但是实际应用中,一般会有多个页面,而且多个页面之间会共享页面的header和footer部分。这样会导致重复编写很多代码。

在使用Jade是我们可以很容易的使用如下代码来实现页面模板功能:

include layout

但是由于Express并非直接支持Handlerbars,所以要实现这个功能还需要一定的设置。在Handlerbars中,可以通过 来实现sub-template的功能。在查找了相关模块之后,我发现了hbs这个Express中间件。

这个模块使用起来很简单,可以完美解决我所遇到的问题。使用方法如下:

  1. 安装模块:

    npm install hbs --save
  2. 设置模板:

    app.set('view engine', 'html');
    app.engine('html', require('hbs').__express);
  3. 注册模板:

    var hbs = require('hbs');
    hbs.registerHelper('helper_name', function(...) { ... });
    hbs.registerPartial('partial_name', 'partial value');

如果需要注册整个文件夹,也可使用如下命令:

var hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials');

这样,我们就可以做到页面模板的重复利用,可以显著减少代码量。

而另外一个关键原因,在于Handlerbars对比Jade,语法更加简单。最重要的还是其普通元素同样使用原生HTML的写法,这样,对于编写样式的同事来讲就会更加友好。使用传统的方式编写样式,可以显著降低学习成本,从而加快项目进度。

而Handerbars所带来的一些其他功能,也会让项目的开发变得更加轻松。

下面附上我项目的基本结构,希望能对同样使用这种方案的同学有一定帮助。

.
├── app.js
├── node_modules
│ ├── express
│ ├── handlebars
│ ├── hbs
│ ├── less-middleware
│ ├── nodemon
│ └── request
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ │ └── app.js
│ ├── lib
│ │ ├── font
│ │ ├── js
│ │ └── stylesheets
│ └── stylesheets
│ ├── style.css
│ └── style.less
├── routes
│ ├── github.js
│ └── index.js
└── views
├── index.hbs
├── orgs.hbs
└── partials
├── footer.hbs
└── header.hbs


【转】在Express项目中使用Handlebars模板引擎的更多相关文章

  1. 在express站点中使用ejs模板引擎

    在express站点中使用ejs模板引擎 文/玄魂 目录 在express站点中使用ejs模板引擎 前言 1.1         安装 1.2修改app.js 1.3创建测试页面 前言 使用 vs创建 ...

  2. Handlebars模板引擎中的each嵌套及源码浅读

    若显示效果不佳,可移步到愚安的小窝 Handlebars模板引擎作为时下最流行的模板引擎之一,已然在开发中为我们提供了无数便利.作为一款无语义的模板引擎,Handlebars只提供极少的helper函 ...

  3. Mongo基础使用,以及在Express项目中使用Mongoose

    MongoDB的基本使用 MongoDB特点: 使用BSON存储数据 支持相对丰富的查询操作(相对其他nosql数据库) 支持索引 副本集(支持多个实例/多个服务器运行同个数据库) 分片(数据库水平扩 ...

  4. 在express项目中使用formidable & multiparty实现文件上传

    安装 formidable,multiparty 模块 npm install formidable,multiparty –save -d 表单上传 <form id="addFor ...

  5. 在express项目中使用redis

    在express项目中使用redis 准备工作 安装redis 安装redis桌面管理工具:Redis Desktop Manager 项目中安装redis:npm install redis 开始使 ...

  6. Handlebars模板引擎之高阶

    Helpers 其实在Handlebars模板引擎之进阶我想说if else的功能的,可是由于这个功能在我的开发中我觉的鸡肋没啥用,就直接不用了. 因为if else只能进行简单判断,如果条件参数返回 ...

  7. handlebars模板引擎使用初探1

    谈到handlebars,我们不禁产生疑问,为什么要使用这样的一个工具呢?它究竟能为我们带来什么样的好处?如何使用它呢? 一.handlebars可以干什么? 首先,我们来看一个案例: 有这样的htm ...

  8. express-9 Handlebars模板引擎(2)

    视图和布局 视图通常表现为网站上的各个页面(它也可以表现为页面中AJAX局部加载的内容,或一封电子邮件,或页面上的任何东西).默认情况下,Express会在views子目录中查找视图.布局是一种特殊的 ...

  9. express-8 Handlebars模板引擎(1)

    简介 使用JavaScript生成一些HTML document.write('<h1>Please Don\'t Do This</h1>'); document.write ...

随机推荐

  1. Gem install rmagick 报错问题~

    本人在CentOS7上在 执行”gem install rmagick“是报错,具体情况如下: 报错如下: [root@localhost ~]# gem install rmagick -v '2. ...

  2. 网站https证书SSL证书相关

    网站https证书SSL证书相关 二级域名可以申请证书来使用,主域名申请的单域名证书,二级域名不在https加密保护内,通配符证书可以保护主域名下所有的二级子域名,二级域名等于和主域名使用的同一张证书 ...

  3. Vue 中如何引入第三方 JS 库

    一绝对路径直接引入全局可用 二绝对路径直接引入配置后import 引入后再使用 三webpack中配置 aliasimport 引入后再使用 四webpack 中配置 plugins无需 import ...

  4. Java包装类之Integer的 "==" 判断数值是否相等的陷阱及原因分析

    在好久以前的一次面试中,面试官问了我这么一个问题:“现在有 Integer a = 56, b = 56, c = 180, d = 180;  请问:a == b ,c == d  是否成立,也就是 ...

  5. QGraphicsItem的paint函数的一些相关问题

    在QGraphicsItem中,一个成员函数paint(),其声明如下: void QGraphicsItem::paint ( QPainter * painter, const QStyleOpt ...

  6. 使用 Nginx 内置 $http_user_agent 来区分( 电脑 pc、手机 mobile、平板 pad )端的内容访问

    location / { #pc端内容访问 set $flag "pc"; set $num 1; set $hua "${http_user_agent}"; ...

  7. radhat6.6上安装oracle12c RAC (二)

    二.GI(Grid Infrastructure)安装 首先将安装包传到node1的目录 2.1 GI软件安装 2.1.1.解压安装包 #su - grid解压 GRID 到 GRID用户的$ORAC ...

  8. 如何在cisco官网上下载Cisco packet tracer模拟器

    这个是“思科网络技术学院”提供的一个软件,需要注册成为学员以后才能用,注册名字可以更改. 进入网站后,上面七个选项,cisco Networking Academy.课程(下边第七个选项“Packet ...

  9. Bootstrap3基础 栅格系统 页面布局随 浏览器大小的变化而变化

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  10. (转载)Unity3D所要知道的基础知识体系大纲,可以对照着学习,不定期更新

    本文献给,想踏入3D游戏客户端开发的初学者. 毕业2年,去年开始9月开始转作手机游戏开发,从那时开始到现在一共面的游戏公司12家,其中知名的包括搜狐畅游.掌趣科技.蓝港在线.玩蟹科技.天神互动.乐元素 ...