在服务器和客户端上使用Handlebars.js的Node.js
我在Node.js中有一个应用程序,使用Expressjs和Handlebars作为模板引擎。
Expressjs使用布局,然后呈现视图。 布局(layout.hbs)如下所示:
<!doctype html> <html lang="en"> <head> </head> <body> {{{body}}} </body> </html>
当你访问一个路由时, {{{body}}}
被replace为node.js中的服务器端。 例如:
app.get('/', function(req, res){ res.render('index'}) })
将用index.hbs的内容replace{{{body}}}
标记。
现在,在客户端,我使用Backbone.js,并希望使用Handlebars来控制通过Backbone控制的视图。 问题是,因为这些网页已经通过把手呈现,所以当我尝试使用其中的把手(或把手内的把手)时,它不起作用。 没有错误,它只是不会用数据replace标签。
有没有人遇到过这个或有任何想法的工作?
谢谢!
是的,这是一个棘手的问题 – 有点像shell脚本中的引用问题,变成老鼠引用引语。
我的解决scheme是在expressjs(服务器端)中使用jade(la haml)为客户端输出基于句柄的模板。 这样,服务器使用一种语法(玉),而客户端使用另一种(句柄)。 我和你在同一个十字路口,所以我有同样的挑战。
当然,翡翠并不是必不可less的(尽pipe它已经为expressjs准备好了)。 您可以为服务器select任何(非句柄)模板引擎,并且/或者您可以使用客户端上的非句柄模板在服务器上使用句柄—只要您select的模板引擎的两种语法不碰撞。 由于我在客户端上使用了emberjs,并且它使用了handlebars语法(默认情况下),所以我更喜欢在客户端上使用emberjs + handlebars语法。 所以expressjs + jade成了服务器的天作之合。
您应该使用预编译的客户端模板。 它们的执行速度更快,并允许您在服务器和客户端上使用相同的模板语言。
- 安装全局的
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);
一个简单的方法就是在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>
上面的代码将在客户端上保存{{..}}标签。
无耻的自我推销!
我想做同样的客户端/服务器共享的事情,所以我写了一个小小的npm包来协助:
节点车把-预编译器
基于wycats的handlebars回购中的命令行编译器,我在几个小时内就把它搞砸了。 这不是世界上最伟大的代码,但它已经为我完成了很好的工作。
编辑:我不再维护这个包。 如果您想接pipe,请通过Github与我联系。 我现在主要使用Jade模板,所以我继续作为维护者是没有意义的。
我通过通过服务器端模板传递客户端模板来解决这个问题。
所以在服务器端读取所有的客户端模板到一个数组,并将其传递给服务器端的渲染函数
在你的路由处理程序中做一些事情:
readTemplates(function(err, clientTemplates) { res.render("page", { clientTemplates: clientTemplates; }); });
然后在layout.hbs中:
{{#each clientTemplates}} <script type="text/handlebars id="{{this.filename}}" > {{{this.template}}} </script> {{/each}}
在这里,我使用没有扩展名的文件名作为模板ID,以便它们可以从Backbone视图中引用。 哦,并记住为生产模式实施caching。
是的,这很糟糕。
我想我们应该为此写一个Handlebars / Express / Connect助手。
你有2个选项。 第二是最好的方式去:
1)逃出胡须
<script type="text/x-handlebars" data-hbs="example"> <p>\{{name}}</p> </script>
2)预编译
这将在服务器上编译模板到客户端之前。 这将使模板准备好使用并减轻浏览器的负担。
我不喜欢预编译的解决scheme(因为我想在我将使用它们的同一个文件中定义模板),也不喜欢天真的\{{
逃生解决scheme(因为它需要完整的Handlebars编译器和更多的JavaScript代码),所以我来了使用Handlebars的助手的混合解决scheme:
1)在服务器configuration上注册一个名为“template”的新帮手
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)在客户端网页的任何地方使用它(用\{{
escape for client-side parameters)
{{#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
- 一旦我开始添加文件到我的控制器文件夹代码中断 – 为什么?
- Passport身份validationfunction在节点API中不起作用
- 无法使用Angular在NodeJS服务器中获取/ html
- 如何从nodejs / express向浏览器发送成功状态?
- Node JS – Express – Mongo DB:在JSON密钥中使用额外的方括号发布数据
- 我怎样才能在jqtpl-node中定义variables
- 我可以在Azure应用程序服务上运行Node / ExpressJS应用程序,还是必须使用Azure Cloud Service?
- NodeJS REST API模型和服务结构
- 用Mongoskin在每个产品的字段描述中查找一个MongoDB文档