0

モデルの属性に基づいてそれ自体をソートするコレクションがあります。モデルを追加して、addイベントハンドラー内で順序を計算したい場合があります。問題は、addイベントハンドラー内でcollection.sort()を呼び出すと、何らかの理由でaddイベントが再度発生することです。

addイベントはいくつかのDOM挿入を行うため、DOMに重複するアイテムが含まれることになります。

これまでのところ、私が見つけた唯一の解決策は、モデルを追加する前に次の順序を計算するか、_。deferを呼び出してコレクションを並べ替えてから、さらにコードを実行することです。

完全なフィドルを参照してください:http://jsfiddle.net/DD23n/9/

4

2 に答える 2

4

sntranは、問題がどこから来ているかについて正しいものです。つまり、配列を反復処理しながら配列を変更しているのです。

nOrder: null モデルリストの最初にある新しいモデルから始めます。

splice.apply(this.models, [index, 0].concat(models));

次に、モデルをループして、イベントをadd トリガー'add'します。

for (i = 0, length = this.models.length; i < length; i++) {
  if (!cids[(model = this.models[i]).cid]) continue;
  options.index = i;
  model.trigger('add', model, this, options);
}

ただし、'add'コールバック内で、モデルを変更します。

if(model.get('nOrder') == null)
    model.set('nOrder', _.max(collection.pluck('nOrder')) + 1);

次に、コレクションを並べ替えます。

collection.sort({silent: true});

これらの2つのアクションは、イベントトリガーループに移動this.models[0]します。this.models[3]しかし、iforそのループはただ刻々と過ぎていき、新しいthis.models[3](以前はにあった0)がif (!cids[(model = this.models[i]).cid])再びテストを通過し、2番目の'add'イベントがあります。

このバージョンのフィドル作品を見て、コレクションの配列が背後でどのように変化しているかを確認できます。

http://jsfiddle.net/ambiguous/p8Fp4/

最も簡単な解決策は、モデルにappend適切な値を設定するメソッドをコレクションに追加してから、それをコレクションに追加することだと思います。nOrder

append: function(m) {
    var nOrder = _.max(this.pluck('nOrder')) + 1;
    if(m instanceof Backbone.Model)
        m.set({ nOrder: nOrder });
    else
        m.nOrder = nOrder;
    this.add(m);
}

その後、'add'コールバックはそのままnOrderにして、コレクションの並べ替えを停止できます。

デモ: http: //jsfiddle.net/ambiguous/JqWVP/

コレクションのメソッドをオーバーライドすることもできますが、add正しく実行したい場合は、はるかに複雑になります。

于 2012-06-07T23:30:24.237 に答える
2

バックボーンのソースコードを読むと、add関数は挿入モデルをに連結しcollection.modelsます。この場合、4つあります。

関数にサイレントを指示しなかったためadd、collection.modelsをループし'add'、挿入要素のイベントをトリガーします。

しかし、あなたはハンドラーを呼び出しsortて、違ったものになります。コレクションがループイン機能を実行すると、挿入モデルは別の位置に配置され、「追加」が再度トリガーされます。addcollection.modelsadd

意味があるかどうかはわかりませんが、ループ中に配列を再配置/変更しない方がよいと思います。

于 2012-06-07T19:25:53.357 に答える