nodejs+express+handlebars整合demo及轉義\問題分析

在分析轉義Handlebars+express問題之前先把nodejs+handlebars+express的項目構建過程說明。 
express 4+handlebars構建項目快捷的方式是: 
這裏寫圖片描述 
如圖可選ejs/jade/hbs等模板引擎,現在我們選hbs(注意express的版本是4.0+)

我選擇整合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');

這個hbsHelper.js是我自己寫的:


var helper = {section: function(name, block){
    if(!this._sections) this._sections = {};
    this._sections[name] = block.fn(this);
    return null;
    }
}
module.exports = helper

3 客戶端頁面views 
layout.hbs

<!DOCTYPE html>
<html>
  <head>
      {{>head}}
      {{{_sections.css}}}
  </head>
  <body>
    {{>header}}
    {{{body}}}
    {{>weather}}
    {{>footer}}
    {{{_sections.js}}}
  </body>
</html>

其中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>

如此就簡要的說明了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": "<p>一大隊</p>",
      "responsiblearea": "陸家嘴,北蔡、六裏、東明部分地區"
    },
    {
      "id": 2,
      "name": "二大隊",
      "responsiblearea": "迪斯尼,北蔡、六裏、東明部分地區"
    },
    {
      "id": 3,
      "name": "三大隊",
      "responsiblearea": "張江高科,北蔡、六裏、東明部分地區"
    }
  ] });
});
module.exports = router;

數據顯示頁面:demo.hbs

<!--demo.hbs的內容會被添加到layout.hbs {{{body}}}裏 
(是否要用佈局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>

這種方式就是在客戶端發出/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;

數據顯示頁面: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}}
        <tr>
               <td>\{{name}}</td>
              <td">{{responsiblearea}}</td>
        </tr>
        \{{/each}}
    </script>
{{/section}}

引用的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();
    });
}

這種方式就是通過ajax請求獲得數據daduis, 通過Handlebars.compile 編譯模板$("#tableList_template"),最後template(data)把數據注入模板並且把dom innerHTML填入到$("#tableList")裏。

問題: 
仔細看<script id="tableList_template" type="text/x-handlebars-template"></script>裏handlebars大括號的使用方式,是不是每個大括號前面都有\轉義符號? 爲什麼轉義?

加入我們不轉義:

<script id="tableList_template" type="text/x-handlebars-template">
        {{#each daduis}}
        <tr>
               <td>{{name}}</td>
              <td">{{responsiblearea}}</td>
        </tr>
        {{/each}}
    </script>

最後渲染出頁面爲空,不顯示錶格! 
爲啥呢? 
因爲在res.render('base-dd');後,在showDaduiHelper();前,handlebars已經將tableList_template裏的數據進行注入並渲染成dom,由於res.render('base-dd')未傳參數,daduis自然就是null,也就不會執行{{#each daduis}},所以是空的!,如圖: 
這裏寫圖片描述

所以我們就在所有handlebars標籤前面加上轉義符號“\”,這樣第一次加載渲染頁面的時候,服務端視圖引擎就“不認識”這些handlebars標籤,如圖: 
這裏寫圖片描述

從而躲過第一次由服務端render引發的數據注入,再執行$(document).ready(function(){ showDaduiHelper();});後,客戶端通過ajax主動請求數據,重新編譯模板並加載數據, 渲染出正確的dom。

結合express: http://wiki.jikexueyuan.com/project/express-mongodb-setup-blog/handlebars.html

使用Handlebars模塊化你的頁面:https://www.jianshu.com/p/a38ec7ef339a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章