我一直在寻找并找到了很多答案,但似乎都没有。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
Shopping Cart
</title>
<link rel="stylesheet" href="lib/style.css" type="text/css">
</head>
<body>
<script id="rtemp" type="text/x-underscore-template"">
<span><%= title %></span>
</script>
<script src="lib/jquery.js" type="text/javascript"></script>
<script src="lib/underscore.js" type="text/javascript"></script>
<script src="lib/backbone.js" type="text/javascript"></script>
<script src="lib/script.js" type="text/javascript"></script>
</body>
<script>
var Photo = Backbone.Model.extend({
initialize: function(){
console.log('this model has been initialized');
this.bind("change:title", function(){
var title = this.get("title");
console.log("My title has been changed to.. " + title);
var pv = new PhotoView();
pv.render();
});
},
setTitle: function(newTitle){
this.set({ title: newTitle });
},
setLocation: function(newLoc)
{
this.set({location:newLoc});
}
});
var PhotoView = Backbone.View.extend
({
el: $('body'),
render: function(event)
{
var name = myPhoto.get('title');
console.info(name);
var template = _.template($('#rtemp').html(), {title:name});
console.info(this.model);
$(this.el).html(template);
return this;
}
});
</script>
</html>
首先;
创建方法的新实例
var newPhoto = new Photo();
newPhoto.setTitle('Fishing');
这项工作很好,它会通过模板加载到身体。但是,如果我再这样做,
newPhoto.setTitle('Sailing');
我收到错误 - “无法调用方法'替换'null'
没有线路错误,但我相信它在
var template = _.template($('#rtemp').html(), {title:name});
答案 0 :(得分:23)
这里有一些问题。
您的模板在"
属性中有两个type
,它应该是:
<script id="rtemp" type="text/x-underscore-template">
您的观看次数render
引用myPhoto
时应为this.model
:
var name = this.model.get('title');
您的主要问题是,您的视图使用<body>
作为this.el
,而您的模板位于<body>
内。
在渲染视图时,您完全替换<body>
的内容:
$(this.el).html(template);
所以在第一次render
通话后,不再有#rtemp
。然后,在下一个render
电话中,您可以尝试:
var template = _.template($('#rtemp').html(), ...);
但由于#rtemp
不再存在于DOM中,所以一切都崩溃了。
如果您立即抓取模板:
var PhotoView = Backbone.View.extend({
el: $('body'),
template: _.template($('#rtemp').html()),
//...
});
然后在this.template()
中使用render
:
render: function(event) {
//...
var template = this.template({
title: name
});
//...
}
你会有更好的运气。当然,您需要确保使用此方法在文档就绪处理程序中定义视图,或者在定义视图时#rtemp
可能不可用。
演示:http://jsfiddle.net/ambiguous/dwGsM/
那就是说,你的应用程序结构相当奇怪。你有一个模型可以监听自己,然后模型创建并在某些内容发生变化时呈现视图。听自己的模型本身就很好,但通常你会听到模型的视图,当模型发生变化时,视图会重新渲染(或者只是部分)。
您的模型看起来应该更像这样:
var Photo = Backbone.Model.extend({
setTitle: function(newTitle) {
this.set({ title: newTitle });
},
setLocation: function(newLoc) {
this.set({ location: newLoc });
}
});
然后你的观点如下:
var PhotoView = Backbone.View.extend({
el: $('body'),
template: _.template($('#rtemp').html()),
initialize: function() {
_.bindAll(this, 'render');
this.model.on('change:title', this.render);
},
render: function(event) {
this.$el.html(
this.template(this.model.toJSON())
);
return this;
}
});
_.bindAll
中的initialize
可确保使用右this.render
调用this
;然后initialize
绑定到事件,以便它可以响应模型中的更改。视图知道它关心什么,因此它负责处理模型中的更改。在render
中,您通常只需调用toJSON
即可获取模板的数据。此外,较新版本的Backbone在视图中包含$(this.el)
的缓存版本this.$el
,因此您不必再自己$(this.el)
。
然后你就这样开始了:
var newPhoto = new Photo();
var viewPhoto = new PhotoView({ model: newPhoto });
newPhoto.setTitle('Fishing');
newPhoto.setTitle('Sailing');
通过在创建视图时指定model
选项,告诉视图要使用的模型。
您可能还想将模板<script>
移出<body>
。
新的和改进的演示:http://jsfiddle.net/ambiguous/Kytw7/