是否有一种简单的方法可以将新模型项插入backbone.js Collection
的中间,然后更新集合的View
以将新项目包含在正确的位置?
我正在使用控件来添加/删除列表中的项目。每个列表项都有自己的Model
和View
,我对整个集合也有View
。
每个项目视图都有一个Duplicate
按钮,用于克隆项目的模型,并将其插入到点击项目下方索引位置的集合中。
将项目插入集合很简单,但我无法弄清楚如何更新集合视图。我一直在尝试这样的事情:
ListView = Backbone.View.extend({
el: '#list-rows',
initialize: function () {
_.bindAll(this);
this.collection = new Items();
this.collection.bind('add', this.addItem);
this.render();
},
render: function () {
this.collection.each(this.addItems);
return this;
},
addItem: function (item) {
var itemView = new ItemView({ model: item }),
rendered = itemView.render().el,
index = this.collection.indexOf(item),
rows = $('.item-row');
if (rows.length > 1) {
$(rows[index - 1]).after(rendered);
} else {
this.$el.append(rendered);
}
}
}
这个实现很有效,但是当我添加一个新项目时,我会遇到奇怪的错误。我相信我可以解决这些问题,但是......
我脑子里有一个声音告诉我,有更好的方法可以做到这一点。必须手动找出插入新ItemView
的位置似乎真的很难 - 集合视图是否应该知道如何重新渲染集合?
有什么建议吗?
答案 0 :(得分:9)
我不认为在添加新元素时重新渲染整个集合是最佳解决方案。它比在正确的位置插入新项目慢,特别是如果列表很长。
另外,请考虑以下方案。您在集合中加载了一些项目,然后添加了n
个项目(比如用户单击“加载更多”按钮)。为此,您可以调用fetch()
方法作为选项之一传递add: true
。当从服务器收回数据时,“添加”事件会被n
次触发,您最终会重新呈现列表n
次。
我实际上在你的问题中使用了代码的变体,这是我对'add'事件的回调:
var view, prev, prev_index;
view = new ItemView({ model: new_item }).render().el;
prev_index = self.model.indexOf(new_item) - 1;
prev = self.$el.find('li:eq(' + prev_index + ')');
if (prev.length > 0) {
prev.after(view);
} else {
self.$el.prepend(view);
}
所以,基本上我只是使用:eq()
jQuery选择器而不是像你那样获取所有元素,应该使用更少的内存。
答案 1 :(得分:4)
我正常做的就是让ListView
在其ItemView
函数中呈现每个render
。然后我将add
事件绑定到render
函数,如下所示:
ListView = Backbone.View.extend({
el: '#list-rows'
, initialize: function () {
_.bindAll(this);
this.collection = new Items();
this.collection.bind('add', this.render);
this.render();
}
, render: function () {
this.$el.empty();
var self = this;
this.collection.each(function(item) {
self.$el.append(new ItemView({ model: item }).render().el);
});
return this;
}
}
每当您致电this.collection.add(someModel, {at: index})
时,视图都会相应地重新呈现。