2012-04-17 49 views
15

我已经看到了几种不同的方式从集合中获取下一个或以前的模型,但想知道是否有人可以提供一些建议,以便我决定实施它。我的收藏是有序的,但我排序的ID不保证是连续的。它只保证是唯一的。假设较小的ID是集合的“较旧”条目,较大的ID是“较新”。从集合中获取下一个和以前的模型

MyCollection = Backbone.Collection.extend({ 
    model: MyModel, 
    initialize:function(){ 
    this.getElement = this._getElement(0); 
    }, 
    comparator: function(model) { 
    return model.get("id"); 
    }, 
    _getElement: function (index){ 
    var self = this; 
    return function (what){ 
    if (what === "next"){ 
     if (index+1 >= self.length) return null; 
     return self.at(++index); 
    } 
    if (what === "prev"){ 
     if (index-1 < 0) return null; 
     return self.at(--index); 
    } 
    // what doesn't equal anything useful 
    return null; 
    }; 
    } 
}); 

当使用getElement,我不喜欢的东西getElement(“下一步”)而getElement(“上一页”),要求我的集合中的一个或下一个模型。从getElement返回的是实际模型,而不是索引。我知道关于collection.indexOf,但我想要一种方式来循环一个集合,而不需要先创建一个模型。这个实现比它需要的更难吗?

回答

23

我会做这样的事情。请记住,目前没有任何错误处理,所以如果您当前处于集合中的第一个模型,并尝试获取之前的错误,您可能会遇到错误。

MyCollection = Backbone.Collection.extend({ 
    model: MyModel, 
    initialize:function(){ 
    this.bindAll(this); 
    this.setElement(this.at(0)); 
    }, 
    comparator: function(model) { 
    return model.get("id"); 
    }, 
    getElement: function() { 
    return this.currentElement; 
    }, 
    setElement: function(model) { 
    this.currentElement = model; 
    }, 
    next: function(){ 
    this.setElement(this.at(this.indexOf(this.getElement()) + 1)); 
    return this; 
    }, 
    prev: function() { 
    this.setElement(this.at(this.indexOf(this.getElement()) - 1)); 
    return this; 
    } 
}); 

要前进到下一个模型collection.next()。前进到下一个模型并返回它var m = collection.next().getElement();

更好地解释next/prev如何工作。

// The current model 
this.getElement(); 
// Index of the current model in the collection 
this.indexOf(this.getElement()) 
// Get the model either one before or one after where the current model is in the collection 
this.at(this.indexOf(this.getElement()) + 1) 
// Set the new model as the current model 
this.setElement(this.at(this.indexOf(this.getElement()) + 1)); 
+0

我喜欢你的一些想法,特别是在初始化方法中使用this.at()。虽然你的代码虽然很长。如果没有其他人提出任何更好和/或更简洁的建议,您将得到绿色检查:-)我的方法更短,并且在到达任何一端时通过返回null来防止脱落到集合的末尾。 – 2012-04-18 16:52:42

+0

您可以通过抛弃'set/getElement'函数并直接访问'currentElement'值来缩短它。 – abraham 2012-04-20 03:03:59

+4

如果使用v0.9 +,你需要有this.setElement(this.at(0));目前在创建集合之后调用的初始化函数中。这是因为在Collection创建模型之前调用initialize。例如:var myCollection = new MyCollection(data); myCollection.setElement(this.at(0)); – 2012-07-17 01:43:00

6

我这样做的方式稍有不同,因为我将方法添加到模型而不是集合中。这样,我可以抓住任何模型,并获得序列中的下一个模型。

next: function() { 
    if (this.collection) { 
     return this.collection.at(this.collection.indexOf(this) + 1); 
    } 
}, 
prev: function() { 
    if (this.collection) { 
     return this.collection.at(this.collection.indexOf(this) - 1); 
    } 
}, 
+0

尽管我喜欢这种方法,但在实践中还存在一些问题。 1.您需要将自定义的“集合”属性添加到您的模型中,该模型引用了您要使用的特定集合。这假设你的模型只是一个集合的成员,但情况可能并非如此。骨干的架构让模型“在黑暗中”可以说是关于收集和观看它的观点,以确保松耦合和灵活性。 2.如果this.collection.indexOf(this)<= 0 ||,这些方法会抛出错误this.collection.indexOf(this)> = collection.size()。 – 1nfiniti 2014-01-13 17:50:34

+0

@mikeyUX我同意只能属于一个集合可以是限制性的,那就是骨干方式。我个人认为在Backbone中应该有一些List实现,它只是用于模型'集合',但没有所有服务器端的东西,所以你可以更容易地完成多个集合。 此外,你可以很容易地调换它,所以它是一个将模型作为参数的集合方法:'''collection.next(model);''' 最后,这不会导致你提出的场景 - 它返回undefined,这是预期的! – Tom 2014-01-15 09:28:33

2

碰碰这个古老的线程有一个较为通用的解决方案:

东西添加到Collection.prototype

current: null, 

initialize: function(){ 
    this.setCurrent(0); 
    // whatever else you want to do here... 
}, 

setCurrent: function(index){ 
    // ensure the requested index exists 
    if (index > -1 && index < this.size()) 
     this.current = this.at(index); 
    else 
     // handle error... 
}, 

// unnecessary, but if you want sugar... 
prev: function() { 
    this.setCurrent(this.at(this.current) -1); 
}, 
next: function() { 
    this.setCurrent(this.at(this.current) +1); 
} 

那么你可以使用糖的方法来获得分组/下一个型号像这样...

collection.prev(); 
collection.next(); 
0

My Backbo ne SelectableCollection类:

Backbone.Collection.extend({ 
    selectNext: function() { 
     if(this.cursor < this.length - 1) { 
      this.cursor++; 
      this.selected = this.at(this.cursor); 
      this.trigger('selected', this.selected); 
     } 
    }, 

    selectPrevious: function() { 
     if(this.cursor > 0) { 
      this.cursor--; 
      this.selected = this.at(this.cursor); 
      this.trigger('selected', this.selected); 
     } 
    }, 
    selectById: function (id) { 
     this.selected = this.get(id); 
     this.cursor = this.indexOf(this.selected); 
     this.trigger('selected', this.selected); 
    }, 
    unselect: function() { 
     this.cursor = null; 
     this.selected = null; 
     this.trigger('selected', null); 
    } 
}); 
相关问题