Backbone.js 从集合中获取下一个和上一个模型
我已经看到了一些从集合中获取下一个或上一个模型的不同方法,但是我想知道是否有人可以就我决定实现它的方式提供一些建议。我的集合已排序,但我正在排序的id不能保证是连续的。它只保证是独一无二的。假设较小的ID是集合中的“旧”项,较大的ID是“新”项Backbone.js 从集合中获取下一个和上一个模型,backbone.js,Backbone.js,我已经看到了一些从集合中获取下一个或上一个模型的不同方法,但是我想知道是否有人可以就我决定实现它的方式提供一些建议。我的集合已排序,但我正在排序的id不能保证是连续的。它只保证是独一无二的。假设较小的ID是集合中的“旧”项,较大的ID是“新”项 MyCollection=Backbone.Collection.extend({ 型号:MyModel, 初始化:函数(){ this.getElement=this.\u getElement(0); }, 比较器:功能(模型){ 返回模型。获取(“
MyCollection=Backbone.Collection.extend({
型号:MyModel,
初始化:函数(){
this.getElement=this.\u getElement(0);
},
比较器:功能(模型){
返回模型。获取(“id”);
},
_getElement:函数(索引){
var self=这个;
返回函数(什么){
如果(什么==“下一步”){
if(index+1>=self.length)返回null;
返回自.at(++索引);
}
如果(什么==“上一个”){
如果(索引-1<0)返回null;
在(--指数)处返回自身;
}
//什么不等于什么有用的东西
返回null;
};
}
});
使用getElement时,我会执行诸如getElement(“next”)和getElement(“prev”)之类的操作来请求集合中的下一个或上一个模型。从getElement返回的是实际的模型,而不是索引。我知道collection.indexOf,但我想找到一种在集合中循环的方法,而不必首先从一个模型开始。这个实现比需要的更难吗?我会这样做。请记住,当前没有任何错误处理,因此,如果当前处于集合中的第一个模型,并尝试获取前一个模型,则可能会出现错误
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()代码>
更好地解释下一步/上一步的工作原理
// 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));
我的做法略有不同,因为我将方法添加到模型中,而不是集合中。这样,我可以抓取任何模型,然后得到序列中的下一个
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);
}
},
用一个更通用的解决方案替换这个旧线程:
要添加到集合中的内容。原型
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);
}
我的主干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);
}
});
Backbone.Collection.extend({
选择下一步:函数(){
if(this.cursor0){
这个光标--;
this.selected=this.at(this.cursor);
this.trigger('selected',this.selected);
}
},
selectById:功能(id){
this.selected=this.get(id);
this.cursor=this.indexOf(this.selected);
this.trigger('selected',this.selected);
},
取消选择:函数(){
this.cursor=null;
this.selected=null;
this.trigger('selected',null);
}
});
我喜欢你的一些想法,特别是在initialize方法中使用这个.at()。不过,您的代码相当长。如果没有其他人提出更好和/或更简洁的建议,您将获得绿色复选框:-)我的方法更短,并且在到达集合的任一端时返回null,从而防止从集合的末尾脱落。您可以通过放弃set/getElement
函数并直接访问currentElement
值来缩短它。如果使用v0.9+,则需要使用此.setElement(此.at(0))); 当前在创建集合后调用的初始化函数中。这是因为在集合创建模型之前会调用initialize。e、 g.:var myCollection=新的myCollection(数据);myCollection.setElement(此.at(0));正如Denis所说,此解决方案不再适用于backbon 0.9+,您需要在初始化后以某种方式设置起始元素。可以通过在重置事件上绑定init来设置起始元素。我是这样做的:initialize:function(){this.bind('reset',this.init,this);},init:function(){this.setElement(this.at(0));},
虽然我喜欢这种方法,但在实践中存在一些问题。1.您需要向模型添加一个自定义“集合”属性,该属性引用要使用的特定集合。这假设您的模型只是单个集合的一个成员,情况可能并非如此。主干网的体系结构使模型“处于黑暗中”,可以说,是关于监视模型的集合和视图,以确保松散耦合和灵活性。2.如果this.collection.indexOf(this)=collection.size(),这些方法将抛出错误。@mikeyUX我同意,只能属于单个集合可能会受到限制,这是主干方式。我个人认为主干网中应该有一些列表实现,只用于模型“集合”,而不需要所有服务器端的东西,因此您可以更轻松地执行多个集合之类的操作。此外,您还可以轻松地交换它,使其成为集合上以模型作为参数的方法:collection.next(model)代码>最后,这不会在您建议的场景中导致错误-它返回未定义的,这是预期的!
collection.prev();
collection.next();
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);
}
});