Node.js与服务器和客户端上的Handlebars.js
Node.js with Handlebars.js on server and client
我在Node.js中有一个应用程序,使用Expressjs和Handlebars作为模板引擎。
Expressjs使用布局,然后渲染视图。布局(layout.hbs)如下所示:
<!doctype html>
<html lang="en">
<head>
</head>
<body>
{{{body}}}
</body>
</html>
当您访问路由时,{{{body}}}
在node.js中的服务器端被替换。例如:
app.get('/', function(req, res){
res.render('index'})
})
将用index.hbs.的内容替换{{{body}}}
标签
现在,在客户端,我使用Backbone.js,并希望使用Handlebars来处理通过Backbone控制的视图。问题是,因为这些页面已经通过Handlebars呈现,所以当我尝试在其中使用Handlebars(或Handlebars中的Handlebars)时,它不起作用。没有错误,只是没有用数据替换标记。
以前有人遇到过这种情况吗?或者有任何解决办法的想法吗?
谢谢!
您应该使用预编译的客户端模板。它们执行速度更快,允许您在服务器和客户端上使用相同的模板语言。
- 全球安装把手
npm install handlebars -g
- 预编译模板
handlebars client-template1.handlebars -f templates.js
- 包含templates.js
<script src="templates.js"></script>
- 执行模板
var html = Handlebars.templates["client-template1"](context);
https://stackoverflow.com/a/13884587/8360
一种简单的方法是在Handlebars文件中的{{
之前附加一个'
。例如:
<script type="text/x-template" id="todo-item-template">
<div class="todo-view">
<input type="checkbox" class="todo-checkbox" '{{checked}}>
<span class="todo-content" tabindex="0">'{{text}}</span>
</div>
<div class="todo-edit">
<input type="text" class="todo-input" value="'{{text}}">
</div>
<a href="#" class="todo-remove" title="Remove this task">
<span class="todo-remove-icon"></span>
</a>
上面的代码将在客户端上呈现,并保留{{..}}标记。
我的解决方案是在expressjs(服务器端)中使用jade(a la haml)为客户端输出基于手柄的模板。通过这种方式,服务器使用一种语法(jade),客户端使用另一种语法。我和你处于同一个十字路口,所以我面临着同样的挑战。
当然,玉不是必不可少的(尽管它是为expressjs准备的)。你可以为服务器选择任何(非手柄)模板引擎,和/或你可以在服务器上使用手柄和在客户端上使用非手柄模板——只要你选择的模板引擎的两种语法不冲突。由于我在客户端上使用emberjs,并且它使用了handlebas语法(默认情况下),所以我更喜欢在客户端上用emberjs+handlebas句法。因此expressjs+jade成为服务器的天然选择。
无耻的自我推销
我想做同样的客户端/服务器共享,所以我写了一个小的npm包来帮助:
节点把手预编译器
我在几个小时内根据wycats的handlebas repo中的命令行编译器快速完成了它。这不是世界上最伟大的代码,但它很好地完成了我的工作。
编辑:我不再维护此程序包。如果你想接任,请通过Github与我联系。我现在主要使用Jade模板,所以继续作为维护人员是没有意义的
我通过将客户端模板传递到服务器端模板来解决这个问题。
因此,在服务器端,将所有客户端模板读取到一个数组中,并将其传递给服务器端上的渲染函数
在您的路线处理程序中执行以下操作:
readTemplates(function(err, clientTemplates) {
res.render("page", {
clientTemplates: clientTemplates;
});
});
然后在布局中。bbs:
{{#each clientTemplates}}
<script type="text/handlebars id="{{this.filename}}" >
{{{this.template}}}
</script>
{{/each}}
在这里,我使用没有扩展名的文件名作为模板id,这样它们就可以从主干视图中引用。哦,记住为生产模式实现缓存。
是的,这太糟糕了。
我认为我们应该为此编写一个Handlebars/Express/Connect帮助程序。
我不喜欢预编译解决方案(因为我想在使用模板的同一文件中定义模板),也不喜欢简单的'{{
转义解决方案(由于它需要完整的Handlebars编译器和更多的javascript代码),所以我想出了一个使用Handlebars助手的混合解决方案:
1) 在服务器配置上注册一个名为"模板"的新助手
var hbs = require('hbs');
hbs.registerHelper("template", function(key, options){
var source = options.fn().replace("''{{", "{{");
var ret =
'<script>'n' +
key + ' = function(opt){'n' +
'return Handlebars.template(' + hbs.handlebars.precompile(source) + ')(opt);'n' +
'}'n' +
'</script>';
return ret;
});
2) 在客户端网页的任何位置使用它(客户端参数使用'{{
转义)
{{#template "myTemplate"}}
<div>
<p>Hello '{{this.name}}!</p>
</div>
{{/template}}
(服务器将以类似的方式对其进行预编译)
<script>
myTemplate = function(opt){
return Handlebars.template(/* HBS PRECOMPILATED FUNCTION */)(opt);
}
</script>
3) 只需在客户端javascript 中调用需要的函数
var generatedHtml = myTemplate("world"); // = <div><p>Hello world!</p></div>
$("#myDiv").html(generatedHtml); // or whatever
您有两个选项。第二种是最好的方法:
1) 逃离胡子
<script type="text/x-handlebars" data-hbs="example">
<p>'{{name}}</p>
</script>
2)预编译
这将在模板到达客户端之前在服务器上编译模板。这将使模板可以随时使用,并减轻浏览器的负担。
- Backbone.js&Handlebars.js来创建相对URL
- 在Handlebars.js中的新行上打印输出
- 递归Handlebars.js模板.如何确定深度
- 如何将这个Json映射到Handlebars js
- 获取模板是用我的Node.JS应用程序的新版本Handlebars错误预编译的
- 如何使用Handlebars.js按状态拆分对象数组
- Handlebars js未在对象上迭代
- 使用Handlebars.js重新呈现HTML中的变量
- 在Meteor.JS Handlebars中将对象转换为数组后无法拆分字符串
- Handlebars.js打印对象没有'不起作用
- Handlebars.js和链接标记
- 在Handlebars.js中查询块帮助程序
- 使用Require.js未定义Handlebars
- 在 Handlebars.js 中呈现部分时向上下文添加属性
- 如何使用 Handlebars.js 访问 JSON 对象
- 使用 Handlebars.js 处理 executeSql 语句的结果
- 如何在 Node.js 中使用 Express、Handlebars 和 Conslidate 设置部分的路径
- 如何在 Handlebars.js 模板上绑定数据以进行自动值更新
- Node.js与服务器和客户端上的Handlebars.js
- Ember.js Handlebars BoundHelper Uncaught TypeError: Object #