您的位置:首页 > Web前端 > Node.js

nodejs+express+handlebars整合demo及转义\问题分析

2017-01-04 20:54 609 查看
在分析转义Handlebars+express问题之前先把nodejs+handlebars+express的项目构建过程说明。

express 4+handlebars构建项目快捷的方式是:



如图可选ejs/jade/hbs等模板引擎,现在我们选hbs(注意express的版本是4.0+)

express --hbs demo


我选择整合handlebars的方式是在已有的nodejs项目上引入

express-handlebars github地址:github

在已有express4 构建的项目上安装
npm install express-handlebars


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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息