我几周就在乱用Backbone并根据教程做了一些简单的应用程序。现在我再次从头开始尝试使用Backbone提供的优秀功能。
我的观点妨碍了。当页面加载时,它会呈现正常并通过迭代集合来创建其嵌套视图。 当我再次调用render()来刷新一个条目的整个列表时,所有视图属性似乎都是未定义的。
单个条目的模型:
Entry = Backbone.Model.extend({
});
条目列表:(json.html是数据区占位符)
EntryCollection = Backbone.Collection.extend({
model: Entry,
url: 'json.html'
});
var entries = new EntryCollection();
查看单个条目,填充Underscore模板并在模型更改时重新呈现。
EntryView = Backbone.View.extend({
template: _.template($('#entry-template').html()),
initialize: function(){
this.model.on('change', this.render);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
查看整个条目列表的列表,这些条目为集合中的每个项目呈现EntryView,如果添加了新项目,则应重新呈现。该按钮用于测试目的。
EntryListView = Backbone.View.extend({
tagName: 'div',
collection: entries,
events: {
'click button': 'addEntry'
},
initialize: function(){
this.collection.on('add',this.render);
},
render: function(){
this.$el.append('<button>New</button>'); //to test what happens when a new item is added
var els = [];
this.collection.each(function(item){
els.push(new EntryView({model:item}).render().el);
});
this.$el.append(els);
$('#entries').html(this.el);
return this;
},
addEntry: function(){
entries.add(new Entry({
title: "New entry",
text: "This entry was inserted after the view was rendered"
}));
}
});
现在,如果我从服务器获取集合,则视图呈现正常:
entries.fetch({
success: function(model,response){
new EntryListView().render();
}
});
只要单击按钮将项目添加到集合中,EntryListView上的事件处理程序就会捕获&#39;添加&#39;事件和调用render()。但是如果我在渲染函数中设置断点,我可以看到所有属性似乎都是&#34;未定义&#34;。没有el
,没有collection
...
我哪里错了? 感谢您的协助,
罗伯特
答案 0 :(得分:4)
原样,EntryListView.render
没有绑定到特定的上下文,这意味着范围(this
)由调用者设置:当您单击按钮时,这将设置为您的集合
您有多种方法可以解决您的问题:
在应用on
initialize: function(){
this.collection.on('add', this.render, this);
},
render
功能绑定到您的视图
initialize: function(){
_.bindAll(this, 'render');
this.collection.on('add', this.render);
},
使用listenTo
在调用时为函数提供正确的上下文
initialize: function(){
this.listenTo(this.collection, 'add', this.render);
},
您通常会执行2或/和3,_.bindAll
为您提供有保证的上下文,listenTo
在您销毁视图时增加了好处
initialize: function(){
_.bindAll(this, 'render');
this.listenTo(this.collection, 'add', this.render);
},
如果我可以:
像
这样的东西var EntryListView = Backbone.View.extend({
events: {
'click button': 'addEntry'
},
initialize: function(){
_.bindAll(this, 'render');
this.listenTo(this.collection, 'reset', this.render);
this.listenTo(this.collection, 'add', this.render);
},
render: function(){
var els = [];
this.collection.each(function(item){
els.push(new EntryView({model:item}).render().el);
});
this.$el.empty();
this.$el.append(els);
this.$el.append('<button>New</button>');
return this;
},
addEntry: function(){
entries.add(new Entry({
title: "New entry",
text: "This entry was inserted after the view was rendered"
}));
}
});
var view = new EntryListView({
collection: entries,
el: '#entries'
});
view.render();
entries.fetch({reset: true});