原文: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. class类 __repr__ 与__str__

    >>> class Student(object):... def __init__(self, name):... self.name = name... def __str__( ...

  2. postgresql 自定义聚合函数

    方法1 CREATE OR REPLACE FUNCTION public.sfun_test1( results numeric[], val numeric) RETURNS numeric[] ...

  3. CCF CSP 201612-1 中间数

    题目链接:http://118.190.20.162/view.page?gpid=T52 问题描述 试题编号: 201612-1 试题名称: 中间数 时间限制: 1.0s 内存限制: 256.0MB ...

  4. mysql之统一刷表

    统一刷表: update report set pdfPath= CONCAT(pdfPath ,substring_index(fileLink, '\\', -1)); update report ...

  5. 在java中如何处理日期格式问题

    1.最简洁的办法就是在对应的对象中加注解 如下一个例子: @DateTimeFormat(pattern="yyyy-MM-dd") @JsonFormat(pattern=&qu ...

  6. 7.JAVA基础复习——JAVA中的设计模式单例模式

    设计模式:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 总体来说设计模式分为23种三大类: 创建型模式,共 ...

  7. Typescript日期Date如何做格式化字符串

    ·使用一个date-fns/format的库 安装npm i date-fns --save import format from 'date-fns/format'; const newdate = ...

  8. 分布式事务、多数据源、分库分表中间件之spring boot基于Atomikos+XADataSource分布式事务配置(100%纯动态)

    本文描述spring boot基于Atomikos+DruidXADataSource分布式事务配置(100%纯动态),也就是增加.减少数据源只需要修改application.properties文件 ...

  9. Oh-My-Zsh及主题、插件安装与配置

    切换zsh Manjaro linux默认安装了zsh,其他可能需要先安装 cat /etc/shells #查看本地有哪几种shell chsh -s /bin/zsh #切换到zsh 默认终端启动 ...

  10. C# 数组与集合的区别

    数组:声明数组的时候必须指定数组的长度.数组在内存中是连续的,索引速度很快,赋值和修改也很简单. 数组的容量是固定的,您只能一次获取或设置一个元素的值,而ArrayList或List的容量可根据需要自 ...