简介###

  • 使用JavaScript生成一些HTML
document.write('<h1>Please Don\'t Do This</h1>');
document.write('<p><span class="code">document.write</span> is naughty,\n');
document.write('and should be avoided at all costs.</p>');
document.write('<p>Today\'s date is ' + new Date() + '.</p>');

问题出现在这里:切换上下文环境是困难的。如果你写了大量的JavaSctipt,混合在HTML中会引起麻烦和混乱; 由JavaScript生成的HTML充满了问题:

  • 必须不断地考虑哪些字符需要转义以及如何转义。
  • 使用JavaScript来生成那些自身包含JavaScript代码的HTML会很快让你抓狂。
  • 通常会失去编辑器的语法高亮显示和其他方便的语言特性。
  • 很难发现格式不正确的HTML。
  • 很难直观地分析。
  • 很难让别人读懂你的代码。

模板解决了在目标语言中编写代码的问题,同时也让插入动态数据成为了可能; 只有在某些最简单的情况下才会使用JavaScript生成HTML。

选择模板引擎###

一些可供参考的准则: 参考推荐文章

  • 性能: 希望模板引擎尽可能地快
  • 客户端、服务端或兼而有之: 大多数(但不是所有)模板引擎都可用于客户端和服务器端。如果需要在这两端都使用模板,推荐选择那些在两端都表现优秀的模板引擎。
  • 抽象: 让代码更可读(例如,在普通HTML文本中使用大括号)

Template-Engine-Chooser

Jade###

doctype html                              <!DOCTYPE html>
html(lang="en") <html lang="en">
head <head>
title= pageTitle <title>Jade Demo</title>
script. <script>
if (foo) { if (foo) {
bar(1 + 5) bar(1 + 5)
} }
body </script>
<body>
h1 Jade <h1>Jade</h1>
#container <div id="container">
if youAreUsingJade
p You are amazing <p>You are amazing</p>
else
p Get on it!
p. <p>
Jade is a terse and Jade is a terse and
simple templating simple templating
language with a language with a
strong focus on strong focus on
performance and performance and
powerful features. powerful features.
</p>
</body>
</html>

Jade无疑是少打了很多字,因为不再有尖括号和结束标记。取而代之,它依赖缩进和一些常识性规则,从而更容易表达出自己想要的。Jade具有一个额外的优势:理论上讲,当HTML自身发生改变时,你可以轻松地将Jade定位于HTML版本的最新版本,从而让你的内容更具“前瞻性”。

Handlebars基础###

理解模板引擎的关键在于context(上下文环境):当渲染一个模板时,便会传递给模板引擎一个对象,叫作上下文对象,它能让替换标识运行。

例如,如果上下文对象是{ name: 'Buttercup' },模板是<p>Hello, {{name}}!</p> ,则 {{name}}会被Buttercup替换。如果向模板中传递HTML文本会发生什么呢?例如,上下文换成{ name: '<b>Buttercup</b>' },使用之前的模板得到的结果将是<p>Hello,&lt;b&gt;Buttercup&lt;b&gt;</p>,这或许并不是你想要的。要想解决这个问题,用三个大括号代替两个就可以了:{{{name}}}。

  • 注释: 区分Handlebars注释和HTML注释很重要。示例如下:
{{! super-secret comment }}
<!-- not-so-secret comment -->

假设这是一个服务器端模板,上面的super-secret comment将不会被传递到浏览器,然而如果用户查看HTML源文件,下面的not-so-secret comment就会被看到。

  • 块级表达式

上下文对象:###

{
currency: {
name: 'United States dollars',
abbrev: 'USD',
},
tours: [
{ name: 'Hood River', price: '$99.95' },
{ name: 'Oregon Coast', price: '$159.95' },
],
specialsUrl: '/january-specials',
currencies: [ 'USD', 'GBP', 'BTC' ],
}

传递到如下模板:

<ul>
{{#each tours}}
{{! I'm in a new block...and the context has changed }}
<li>
{{name}} - {{price}}
{{#if ../currencies}}
({{../../currency.abbrev}})
{{/if}}
</li>
{{/each}}
</ul>
{{#unless currencies}}
<p>All prices in {{currency.name}}.</p>
{{/unless}}
{{#if specialsUrl}}
{{! I'm in a new block...but the context hasn't changed (sortof) }}
<p>Check out our <a href="{{specialsUrl}}">specials!</p>
{{else}}
<p>Please check back often for specials.</p>
{{/if}}
<p>
{{#each currencies}}
<a href="#" class="currency">{{.}}</a>
{{else}}
Unfortunately, we currently only accept {{currency.name}}.
{{/each}}
</p>
  • each辅助方法,这使我们能够遍历一个数组; 在下级块中,如果想访问currency对象,就得使用../来访问上一级上下文。

  • if辅助方法:

    在Handlebars中,所有的块都会改变上下文,所以在if块中,会产生一个新的上下文......而这刚好是上一级上下文的副本。换句话说,在if或else块中,上下文与上一级上下文是相同的。但是当在一个each循环中使用if块时就有必要细究一下了。在{{#each tours}}循环体中,可以使用../.访问上级上下文。不过,在{{#if ../currencies}}块中,又进入了一个新的上下文......所以要获得currency对象,就得使用../../.。第一个../获得产品的上下文,第二个获得最外层的上下文。这就会产生很多混乱,最简单的权宜之计就是在each块中避免使用if块。

  • 在if和each块中都有一个可选的else块(对于each,如果数组中没有任何元素,else块就会执行)。我们也用到了unless辅助方法,它基本上和if辅助方法是相反的:只有在参数为false时,它才会执行。

  • 最后要注意的一点是在{{#each currencies}}块中使用{{.}}。{{.}}指向当前上下文,在这个例子中,当前上下文只是我们想打印出来的数组中的一个字符串。

访问当前上下文还有另外一种独特的用法:它可以从当前上下文的属性中区分出辅助方法。例如,如果有一个辅助方法叫作foo,在当前上下文中有一个属性也叫作foo,则{{foo}}指向辅助方法,{{./foo}}指向属性。

服务器端模板###

服务器端模板与客户端模板不同,客户端模板能够通过查看HTML源文看到,而不会看到服务器端模板,或是用于最终生成HTML的上下文对象。

服务器端模板除了隐藏实现细节,还支持模板缓存,这对性能很重要。模板引擎会缓存已编译的模板(只有在模板发生改变的时候才会重新编译和重新缓存),这会改进模板视图的性能。默认情况下,视图缓存会在开发模式下禁用,在生产模式下启用。如果想显式地启用视图缓存,可以这样做:app.set('view cache', true)

Express支持Jade、EJS和JSHTML。所以需要添加一个node包,让Express提供Handlebars支持。

npm install --save express3-handlebars

然后就可以在Express中引入:

var handlebars = require('express3-handlebars').create({ defaultLayout: 'main' });
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');

express3-handlebars让Handlebars模板拥有了.handlebars扩展名。可以在创建express3-handlebats实例将扩展名改成同样常见的.hbs;默认模版还是main.hbs

var exphbs = require('express3-handlebars');
app.engine('hbs', exphbs({extname: '.hbs'}));
app.set('view engine', 'hbs');

express-8 Handlebars模板引擎(1)的更多相关文章

  1. 【转】在Express项目中使用Handlebars模板引擎

    原文:http://fraserxu.me/2013/09/12/Using-Handlebarsjs-with-Expressjs/ 最近在用Expressjs做一个项目,前后端都用它来完成.自己之 ...

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

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

  3. Express ( MiddleWare/中间件 路由 在 Express 中使用模板引擎 常用API

    A fast, un-opinionated, minimalist web framework for Node.js applications. In general, prefer simply ...

  4. Handlebars模板引擎之高阶

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

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

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

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

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

  7. Handlebars 模板引擎之前后端用法

    前言 不知不觉间,居然已经这么久没有写博客了,坚持还真是世界上最难的事情啊. 不过我最近也没闲着,辞工换工.恋爱失恋.深圳北京都经历了一番,这有起有落的生活实在是太刺激了,就如拿着两把菜刀剁洋葱一样, ...

  8. express 4.x 模板引擎与express.static

    前提:要在express中使用模块引擎需要将要使用的模板引擎安装在本项目,当然,express也是要安装的.在下面实例中,我使用的模板引擎是pug(一起叫做jade) 我的目录结构如下: 根目录为st ...

  9. express中ejs模板引擎

    1.在 app.js 中通过以下两个语句设置了 引擎类型 和页面模板的位置: app.set('views', __dirname + '/views'); app.set('view engine' ...

随机推荐

  1. 【hadoop2.6.0】利用Hadoop的 Java API

    Hadoop2.6.0的所有Java API都在 http://hadoop.apache.org/docs/r2.6.0/api/overview-summary.html 里. 下面实现一个利用J ...

  2. jquery $(document).ready() 与window.onload的异同

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的.   1.执行时间     ...

  3. 更新补丁Bind

    1.查询补丁版本信息 (1) rpm -qa|grep bind (2) dig @localhost version.bind 2.下载安装 BIND最新漏洞和升级解决办法 现在有非常多的公司的都有 ...

  4. [Android ] linux命令英文缩写的含义(方便记忆)

    du -sh */ reference to : http://blog.chinaunix.net/uid-27164517-id-3299073.html linux常用命令的英文单词缩写 命令缩 ...

  5. qt_计算器的简单实现

    //阶乘不知道怎么实现不了/(ㄒoㄒ)/~~,以后慢慢调试吧......... //转换为后缀表达式,实现最主要功能 void MainWindow::toPostfix () { QString e ...

  6. 杨辉三角用java实现

    代码如下: public class ErArray { public static void main(String[] args) { //杨辉三角 int[][] num = new int[1 ...

  7. auto(c++11)

    C++primer 第五版,第三章出现了此段程序,求解读附源码:代码1:#include<iostream>#include<string>using namespace st ...

  8. jQuery - 1.简单的JQuery

    1.简单的JQuery 2.jQuery对象(包装集).Dom对象 3.JQuery提供的函数 1.简单的JQuery $(document).ready(function () { alert(&q ...

  9. Power BI for Office 365介绍

    微软在七月份发布了一个新产品,它建立在微软的云的第一个数据平台- Power BI for Office 365.Satya Nadella,服务器和工具业务总裁,在当天的上午在微软的年度全球合作伙伴 ...

  10. 莫队算法 2038: [2009国家集训队]小Z的袜子(hose)

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 ...