2

我有一个 Backbone Collection,我希望它以某种方式响应自己的更新(即添加、删除、重置)。我在各种场景中都遇到过这种情况,但为了讨论,假设我正在计算基于模型 id 的哈希,以快速比较集合:

var HashedCollection = Backbone.Collection.extend({
    updateHash: function() {
        // set a simple hash based on model id
        this.hash = this.pluck('id').sort().join('|');
    } 
});

问题是,让我的哈希保持最新的正确方法是什么?

可能的选项:

  • 为事件设置一个自监听器:

    this.on('add remove reset', this.updateHash, this);
    

    这样做的问题是某些操作可能是静默的,但我仍然想更新哈希 - 这对于第一次设置来说尤其是一个问题,initialize因为集合还没有它的模型,所以这不会发生,并且初始重置事件是静默的(相关代码)。另外,这意味着任何其他组件都可以通过传递{ silent: true }.

  • .add为、.remove.reset和/或设置函数覆盖.set

    set: function() {
        Backbone.Collection.prototype.set.apply(this, arguments);
        this.updateHash();
    }
    // etc
    

    这里最大的问题是处理单个add/set调用与多个调用reset-多次reset调用add,即多次调用set,因此包装set意味着我们将在重置中为每个项目更新一次哈希。如果updateHash比上面的简单示例更昂贵,这可能是一个真正的问题。另一个较小的问题是我最终得到了很多被覆盖的函数,导致更多的半样板代码和核心方法中更多的潜在错误。

为了便于讨论,请假设 a) 计算散列是昂贵的,并且 b) 散列被频繁引用。

这里有没有更好的方法来保持集合状态与其模型保持同步?

4

2 回答 2

1

You don't provide any specific info so it is hard to give a more detailed answer, but in general, you are doing things backwards. You shouldn't update the hash until you actually need it,

getHash : function(){
  return this.pluck('id').sort().join('|');
}

Instead of referring to this.hash you should call this.getHash() whenever you need it. Then all your syncronization problems go away.

If you want to do things when it changes then listen on the collections events, but nothing you said convinces me that there is a situation where a collection needs to listen to itself.

于 2013-07-19T20:33:17.617 回答
1

我可能错了,但我认为你的“最大问题”(你的话)不是问题。

reset调用add一次。

// from backbone source - Backbone.Collection.reset
reset:
... code above ...
this.add(models, _.extend({silent: true}, options)); // note - silent:true
... code below ...

add调用set一次。

// from backbone source - Backbone.Collection.add
add: function(models, options) {
  return this.set(models, _.defaults(options || {}, addOptions));
},

如果您覆盖set(如您所示)updateHash,则只会在重置时调用一次。

set:function() {
  Backbone.Collection.prototype.set.apply(this,arguments);
  this.updateHash();
},

这是一个用于演示的小提琴 - http://jsfiddle.net/5ggCd/

您还需要覆盖remove

remove:function() {
  Backbone.Collection.prototype.remove.apply(this,arguments);
  this.updateHash();
},
于 2013-07-20T04:42:37.210 回答