将项目插入backbone.js集合

时间:2012-03-06 14:17:50

标签: javascript backbone.js

是否有一种简单的方法可以将新模型项插入backbone.js Collection的中间,然后更新集合的View以将新项目包含在正确的位置?

我正在使用控件来添加/删除列表中的项目。每个列表项都有自己的ModelView,我对整个集合也有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的位置似乎真的很难 - 集合视图是否应该知道如何重新渲染集合?

有什么建议吗?

2 个答案:

答案 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})时,视图都会相应地重新呈现。