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)的更多相关文章

  1. js模版引擎handlebars.js实用教程

    js模版引擎handlebars.js实用教程 阅读本文需要了解基本的Handlebars.js概念,本文并不是Handlebars.js基础教程,而是注重于实际应用,为读者阐述使用过程中可能会遇到的 ...

  2. 模版引擎Handlebars和Mustache

    Handlebars是一款很高效的模版引擎,提供语意化的模版语句,最大的兼容Mustache模版引擎, 提供最大的Mustache模版引擎兼容, 无需学习新语法即可使用; 下面这个是基本的模版表达式, ...

  3. js模版引擎handlebars.js实用教程——为什么选择Handlebars.js

    返回目录 据小菜了解,对于java开发,涉及到页面展示时,比较主流的有两种解决方案: 1. struts2+vo+el表达式. 这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是: ...

  4. js模版引擎handlebars.js实用教程——each-基本循环使用方法

    返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...

  5. js模版引擎handlebars.js实用教程——each-循环中使用this

    返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...

  6. js模版引擎handlebars.js实用教程——each嵌套

    <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content="text/ ...

  7. js模版引擎handlebars.js实用教程——循环中使用索引

    <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content="text/ ...

  8. js模版引擎handlebars.js实用教程——with-进入到某个属性(进入到某个上下文环境)

    返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...

  9. js模版引擎handlebars.js实用教程——with-终极this应用

    返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...

随机推荐

  1. Jenkins集成openshift容器中进行代码扫描

    1.Dockerfile sonarDockerfile: (基础slave镜像参考上篇博文) FROM registry.it.com/openshift/jenkins-slave:latest ...

  2. Linux Namespace : 简介

    在初步的了解 docker 后,笔者期望通过理解 docker 背后的技术原理来深入的学习和使用 docker,接下来的几篇文章简单的介绍下 linux namespace 的概念以及基本用法. na ...

  3. Fastreport.net 如何在开发MVC应用程序时使用报表

    当你使用MVC模板创建自己的Web项目,会出现一个合理的问题 - 如何在其中使用FastReport.Net Web报表? 在这篇文章中,我会为你演示如何做到这一点. 由于在MVC体系结构中,视图与逻 ...

  4. 《React Native 精解与实战》书籍连载「React 与 React Native 简介」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  5. find和grep命令合集

    linux grep命令 1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expressi ...

  6. Python_装饰器复习_30

    复习: # 装饰器的进阶 # functools.wraps # 带参数的装饰器 # 多个装饰器装饰同一个函数# 周末的作业 # 文件操作 # 字符串处理 # 输入输出 # 流程控制 # 装饰器# 开 ...

  7. 在java中怎样获得当前日期时间

    Calendar cal = Calendar.getInstance();    java.text.SimpleDateFormat sdf = new SimpleDateFormat(&quo ...

  8. CSS响应式布局实例

    <style type="text/css">        body{            margin:0 auto;            min-width: ...

  9. C调用C++, C++调用C方法

    1. C 调用 C++封装好后的函数: -> 在C++中有一个函数 int main_cpp(): -> 首先构建头文件, #ifndef CPP_FILE_H   #define CPP ...

  10. laravel打印sql

    DB::connection()->enableQueryLog(); print_r(DB::getQueryLog());