我正在使用集合视图来渲染我的模型视图数组。我添加了一个方法,从现有的集合视图中删除单个模型视图,并尝试在新的el:元素中重新呈现它。
我使用collection.get(this.model)
将模型保存到变量中,我将该变量添加到我的新集合中,该集合是与新DOM元素关联的新集合视图的模型,并且我重新使用相同的集合视图渲染方法。当我在console.log()新集合中时,我看到了我从旧集合中选择的模型,但它没有在页面上呈现。
<script>
(function($){
//---------SINGLE ENTRY MODEL----------
var Entry = Backbone.Model.extend({
defaults: function(){
return{
word: '',
definition: ''
}
}
});
//------------ENTRY MODEL COLLECTION------------
var EntryList = Backbone.Collection.extend({
model: Entry
});
//-----INSTANCIATE COLLECTION----
var dictionary = new EntryList();
var saved = new EntryList();
//-----SINGLE ENTRY VIEW------
var EntryView = Backbone.View.extend({
model: new Entry(),
tagName:'div',
events:{
'click .edit': 'edit',
'click .delete': 'delete',
'keypress .definition': 'updateOnEnter',
'click .save': 'save'
},
delete: function(ev){
ev.preventDefault;
dictionary.remove(this.model);
},
edit: function(ev){
ev.preventDefault;
this.$('.definition').attr('contenteditable', true).focus();
},
//method that adds existing model to new collection
save: function(ev){
ev.preventDefault;
var savedEntry = dictionary.get(this.model);
dictionary.remove(this.model);
saved.add(savedEntry);
console.log(savedEntry.toJSON());
},
close: function(){
var definition = this.$('.definition').text();
this.model.set('definition', definition);
this.$('.definition').attr('contenteditable', false).blur();
},
updateOnEnter: function(ev){
if(ev.which == 13){
this.close();
}
},
initialize: function(){
this.template = _.template($("#dictionary_template").html());
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
//--------------DICTIONARY VIEW------------
var DictionaryView = Backbone.View.extend({
model: dictionary,
el: $('#entries'),
initialize: function(){
this.model.on('add', this.render, this);
this.model.on('remove', this.render, this);
},
render: function(){
var self = this;
self.$el.html('');
_.each(this.model.toArray(), function(entry, i){
self.$el.append((new EntryView({model: entry})).render().$el);
});
return this;
}
});
//---------SAVED ENTRY VIEW-----------
var SavedView = Backbone.View.extend({
model: saved,
el: $('#saved'),
initialize: function(){
this.model.on('save', this.savedRender, this);
},
//method that renders new collection view with different el:
savedRender: function(){
var self = this;
self.$el.html('');
_.each(this.model.toArray(), function(saved, i){
self.$el.append((new EntryView({model: savedEntry})).render().$el);
});
return this;
}
});
//-------BINDING DATA ENTRY TO NEW MODEL VIEW-------
$(document).ready(function(){
$('#new-entry').submit(function(ev){
var entry = new Entry({word: $('#word').val(), definition: $('#definition').val() });
dictionary.add(entry);
dictionary.comparator = 'word';
console.log(dictionary.toJSON());
$('.form-group').children('input').val('');
return false;
});
var appView = new DictionaryView();
});
//--------------ROUTER----------------
var Router = Backbone.Router.extend({
routes:{
'':'home'
}
});
var router = new Router();
router.on('route:home', function(){
console.log('router home');
});
Backbone.history.start();
})(jQuery);
</script>
答案 0 :(得分:2)
这里有很多问题。
首先,您没有SavedView
的实例。 var SavedView = Backbone.View.extend(...);
语句只是定义SavedView
类。要拥有此类的活动实例,必须使用new
运算符初始化一个实例。您将需要在代码中的某个位置使用如下所示的行(一个好的位置将位于jQuery就绪处理程序的末尾):
var saved_view = new SavedView();
接下来,我们将研究EntryView
类的save方法。 var savedEntry = dictionary.get(this.model);
语句完全没必要,因为我们知道dictionary.get(this.model)
将返回this.model - 我们显然已经拥有了该实例。因此,我们可以从此方法中删除混乱,并留下以下内容:
ev.preventDefault;
saved.add(this.model);
dictionary.remove(this.model);
但是,我们仍然不在目的地。如果我们将注意力转向SavedView
类定义,我们会看到它将其render方法绑定到其集合上的“save”事件saved
对象。它不是我们应该绑定的“保存”事件,而是“添加”事件 - 因为当我们将模型添加到saved
时将会触发:
this.model.on('add', this.savedRender, this);
如果我们现在测试我们的代码,我们应该在savedEntry
内的SavedView.savedRender
上引用一个引用错误。看起来这是一个拼写错误,打算“保存”。 (您将在下面注意到除了纠正错字之外,我还从该表达式中删除了一组括号,除了使代码不易读之外没有任何功能):
self.$el.append(new EntryView({ model: saved }).render().$el);
编辑:
回答您关于saved
方法中SavedView.savedRender
变量的后续问题:
本例中的saved
对象是单个Entry模型。您混淆的原因是我们重新使用变量名称“已保存”。在_.each回调中,我们定义了第一个被称为“已保存”的参数;这个“已保存”是回调本地的,与之前定义的EntryList
集合无关。在我们的回调中,saved
是saved
集合的元素(yikes!) - 这是为什么变量命名很重要的一课。
当我继续在savedRender
方法中更改“已保存”的名称时,我注意到其他一些重做的重构。我在下面列出了我的重构:
使用Backbone(http://backbonejs.org/)的目的是让我们可以访问对象(模型)和数组(集合)的方便帮助器。 Backbone集合有each
方法我们可以使用而不是将我们的集合传递给Underscore(http://underscorejs.org/)each
。
如上所述,saved
是我们的each
回调参数的可怕名称,因为它在概念上与集合的名称冲突。由于saved
是Entry模型的集合,因此“entry”是一个更合适的名称。
Backbone允许我们将上下文传递给我们在回调中将成为this
的每个回调。这样我们就可以跳过在this
变量中缓存self
的步骤。
我重构的savedRender
变为:
savedRender: function () {
this.$el.empty();
this.model.each(function (entry) {
this.$el.append(new EntryView({ model: entry }).render().$el);
}, this);
return this;
}