带有主干模板的车把未渲染
Posted
技术标签:
【中文标题】带有主干模板的车把未渲染【英文标题】:Handlebars with Backbone template not rendering 【发布时间】:2017-07-09 04:59:41 【问题描述】:我有一个在服务器和客户端上同时使用 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>
尝试了不同的 type 属性,但仍然无法正常工作。
我该如何解决这个问题?任何帮助表示赞赏。谢谢。
在客户端添加了完整的 index.js
/* 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();
);
());
【问题讨论】:
你在哪里初始化index.js
...中的视图?声明一个视图是不够的。您需要在加载所需的内容后对其进行初始化。
@T J 如果你的意思是使用 Backbone.Model.Extend,我把它放在同一个文件中
(function() 'use strict'; app = app || ; app.Contact = Backbone.Model.extend( url: '/contact/', 默认值: 成功: false, errors: [], errfor: , name: '', email: '', message: '' ); 这是带有 Jade 和 Underscore 模板的 github.com/jedireza/drywall。我正在尝试将其更改为车把。
不,您应该在某处拥有new app.ContactView()
。顺便说一句,如果您要共享代码块,请edit 并添加它。它们在 cmets 中是不可读的
$(document).ready(function() app.contactView = new app.ContactView(); );
将初始化视图然后您的应用程序加载。那时index.hbs
的内容是否可用?还是稍后加载?
【参考方案1】:
所以这里提到Handlebars.compile
必须在<script></script>
中的车把模板加载到DOM 之后加载。在这种情况下,使用 express-hanldebars 时,必须在主布局中的 body
元素之后放置指向 js 文件的链接。这是正确的答案。
这里还有一个问题,app
不能像 index.js
为了在全局范围内定义app
,您必须将app = app || ;
移出IIFE 范围并将其放在文件的开头并将其声明为全局变量:var app = app || ;
。如果有多个主干文件,它们都应该实现类似的结构,以便app
是全局的。
【讨论】:
以上是关于带有主干模板的车把未渲染的主要内容,如果未能解决你的问题,请参考以下文章