express 下的handlebars应用

在分析转义Handlebars+express问题之前先把nodejs+handlebars+express的项目构建过程说明。 
express 4+handlebars构建项目快捷的方式是: 
express 下的handlebars应用_第1张图片 
如图可选ejs/jade/hbs等模板引擎,现在我们选hbs(注意express的版本是4.0+)

express --hbs demo
  • 1
  • 1

我选择整合handlebars的方式是在已有的nodejs项目上引入 
express-handlebars github地址:github

  1. 在已有express4 构建的项目上安装npm install express-handlebars
  2. app.js里添加如下内容(替换以前的引擎模板例如ejs):
var exphbs  = require('express-handlebars');
var hbsHelper = require('./util/hbsHelper');

app.set('views', path.join(__dirname, 'views'));
app.engine('.hbs', exphbs({
    layoutsDir: 'views',
    defaultLayout: 'layout',
    extname: '.hbs',
    helpers:hbsHelper
}));
app.set('view engine', '.hbs');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这个hbsHelper.js是我自己写的:


var helper = {section: function(name, block){
    if(!this._sections) this._sections = {};
    this._sections[name] = block.fn(this);
    return null;
    }
}
module.exports = helper
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3 客户端页面views 
layout.hbs


<html>
  <head>
      {{>head}}
      {{{_sections.css}}}
  head>
  <body>
    {{>header}}
    {{{body}}}
    {{>weather}}
    {{>footer}}
    {{{_sections.js}}}
  body>
html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

其中footer(对应目录文件: views/partials/footer.hbs)引入的是js,如下:

<script src="javascripts/lib/jquery.js">script>
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.min.js">script>
  • 1
  • 2
  • 1
  • 2

如此就简要的说明了nodejs+express+handlebars整合过程。

以下是客户端数据请求加载过程说明及问题分析:

客户端页面数据加载

方式一: 向服务端发出路由请求的时候获取数据

路由配置:routes/index.js

var express = require('express');
var router= express.Router();
router.get('/base-dd', function(req, res, next) {
  res.render('base-dd',{ daduis: [
    {
      "id": 1,
      "name": "

一大队

"
, "responsiblearea": "陆家嘴,北蔡、六里、东明部分地区" }, { "id": 2, "name": "二大队", "responsiblearea": "迪斯尼,北蔡、六里、东明部分地区" }, { "id": 3, "name": "三大队", "responsiblearea": "张江高科,北蔡、六里、东明部分地区" } ] }); }); module.exports = router;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

数据显示页面:demo.hbs



                            <section class="panel">              
                                     <table>
                                        <thead>
                                        <tr>  
                                   <th>大队名称th><th>责任区域th>                                           
                                        tr>
                                        thead>
                                        <tbody id="tableList" >
                                        {{#each daduis}}
                                      <td>{{{name}}}td>
                                   <td>{{responsiblearea}}td>
                                        tr>
                                        {{/each}}
                                        tbody>
                                    table>
                            section>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

这种方式就是在客户端发出/base-dd路由请求后,通过路由配置里的res.render(‘base-dd’,{daduis:[..]})实现传参,把数组daduis传到到 {{#each daduis}},通过handlebars模板引擎遍历数组,渲染出一行行带数据的dom(tr)。

方式二:路由配置里不传参数,在页面已经加载完成后,在js($(document).ready(function(){….});)里主动发出ajax请求获取数据。

路由配置:routes/index.js

var express = require('express');
var router= express.Router();
router.get('/base-dd', function(req, res, next) {
  res.render('base-dd');
});
module.exports = router;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

数据显示页面:demo.hbs

    <section class="panel">              
                                     <table>
                                        <thead>
                                        <tr>  
                                   <th>大队名称th><th>责任区域th>                                           
                                        tr>
                                        thead>
                                        <tbody id="tableList" >

                                        tbody>
                                    table>
                            section>

{{#section 'js'}}
    <script src="javascripts/demo.js">script>
    <script id="tableList_template" type="text/x-handlebars-template">
        \{{#each daduis}}
        
               <td>\{{name}}</td>
              {{responsiblearea}}</td>
        tr>
        \{{/each}}
    script>
{{/section}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

引用的demo.js

$(document).ready(function(){
    showDaduiHelper();
});

function showDaduiHelper(){
    $.get("/dadui/queryAll", function(result){
        var data = {daduis:result};
        var source   = $("#tableList_template").html();
        var template = Handlebars.compile(source);
        console.log(data);
        $("#tableList")[0].innerHTML = template(data);
        testHandlebars();
    });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这种方式就是通过ajax请求获得数据daduis, 通过Handlebars.compile 编译模板$("#tableList_template"),最后template(data)把数据注入模板并且把dom innerHTML填入到$("#tableList")里。

问题: 
仔细看里handlebars大括号的使用方式,是不是每个大括号前面都有\转义符号? 为什么转义?

加入我们不转义:

<script id="tableList_template" type="text/x-handlebars-template">
        {{#each daduis}}
        
               <td>{{name}}</td>
              {{responsiblearea}}</td>
        tr>
        {{/each}}
    script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

最后渲染出页面为空,不显示表格! 
为啥呢? 
因为在res.render('base-dd');后,在showDaduiHelper();前,handlebars已经将tableList_template里的数据进行注入并渲染成dom,由于res.render('base-dd')未传参数,daduis自然就是null,也就不会执行{{#each daduis}},所以是空的!,如图: 
这里写图片描述

所以我们就在所有handlebars标签前面加上转义符号“\”,这样第一次加载渲染页面的时候,服务端视图引擎就“不认识”这些handlebars标签,如图: 
express 下的handlebars应用_第2张图片 
从而躲过第一次由服务端render引发的数据注入,再执行$(document).ready(function(){ showDaduiHelper();});后,客户端通过ajax主动请求数据,重新编译模板并加载数据, 渲染出正确的dom

你可能感兴趣的:(express)