我有一个在服务器和客户端上同时使用Backbone和Handlebars的应用程序。
安装了Backbone和Express-Handlebars
app.js
app.set('views', path.join(__dirname, '/views'));
app.engine('.hbs', expHbs({
defaultLayout: 'index',
extname: '.hbs'
}));
app.set('view engine', '.hbs');
index.js
exports.init = function(req, res){
res.render('contact/index');
};
index.hbs
<div class="row">
<div class="col-sm-6">
<div class="page-header">
<h1>Send A Message</h1>
</div>
<div id="contact"></div>
</div>
....some code
<script id="tmpl-contact" type="text/x-handlebars-template">
<form>
bootstrap with handlebars temlates {{....}} in here
</form>
</script>
在客户端,我通过Bower安装了Backbone和Handlebars
在 index.js Backbone.view
中var Handlebars = require('handlebars');
app.ContactView = Backbone.View.extend({
el: '#contact',
template: Handlebars.compile( $('#tmpl-contact').html() ),
events: {
'submit form': 'preventSubmit',
'click .btn-contact': 'contact'
},
initialize: function() {
this.model = new app.Contact();
this.listenTo(this.model, 'sync', this.render);
this.render();
},
render: function() {
this.$el.html(this.template( this.model.attributes ));
this.$el.find('[name="name"]').focus();
},
preventSubmit: function(event) {
event.preventDefault();
},
contact: function() {
this.$el.find('.btn-contact').attr('disabled', true);
this.model.save({
name: this.$el.find('[name="name"]').val(),
email: this.$el.find('[name="email"]').val(),
message: this.$el.find('[name="message"]').val()
});
}
});
会发生什么情况是index.hbs在服务器端正常呈现,但它不会在脚本中呈现表单;它显示为空<div id="contact"></div>
,并且在控制台中没有显示任何错误。
如此处Using Handlebars with Backbone所示,使用把手替换下划线模板的方法只是将_.template
替换为Handlebars.compile
,但这些选项都不适合我。我还为<script>
尝试了不同的类型属性,但它仍无效。
我该如何解决这个问题?任何帮助表示赞赏。感谢。
/* global app:true */
var Handlebars = require('Нandlebars');
(function() {
'use strict';
app = app || {};
app.Contact = Backbone.Model.extend({
url: '/contact/',
defaults: {
success: false,
errors: [],
errfor: {},
name: '',
email: '',
message: ''
}
});
app.ContactView = Backbone.View.extend({
el: '#contact',
template: Handlebars.compile( $('#tmpl-contact').html() ),
events: {
'submit form': 'preventSubmit',
'click .btn-contact': 'contact'
},
initialize: function() {
this.model = new app.Contact();
this.listenTo(this.model, 'sync', this.render);
this.render();
},
render: function() {
this.$el.html(this.template( this.model.attributes ));
this.$el.find('[name="name"]').focus();
},
preventSubmit: function(event) {
event.preventDefault();
},
contact: function() {
this.$el.find('.btn-contact').attr('disabled', true);
this.model.save({
name: this.$el.find('[name="name"]').val(),
email: this.$el.find('[name="email"]').val(),
message: this.$el.find('[name="message"]').val()
});
}
});
$(document).ready(function() {
app.contactView = new app.ContactView();
});
}());
答案 0 :(得分:1)
因为这里提到的Handlebars.compile
必须在<script></script>
中的把手模板加载到DOM后加载。在这种情况下,当使用express-hanldebars时,必须在主布局中的{{{ body }}}
元素之后放置指向js文件的链接。这是正确的答案。
此处还有一个问题是app
无法全局定义,因为它出现在 index.js
为了全局定义app
,您必须将app = app || {};
移到IIFE范围之外,并将其放在文件的开头,并将其声明为全局变量:var app = app || {};
。如果有多个骨干文件,它们都应该实现类似的结构,以便app
是全局的。