17

私が書いた最初の試みで

this.collection.each(function(element){
    element.destroy();
});

ConcurrentModificationExceptionこれは、他のすべての要素が削除されるJavaと同様であるため、機能しません。

提案されているように、モデルで「remove」イベントをバインドしてそれ自体を破棄しようとしました。コレクション内のバックボーンモデルを1つのステップで破棄しますか?、ただし、コレクションに属するモデルでdestroyを呼び出すと、2つの削除要求が発生します。

アンダースコアのドキュメントを確認しましたeach()が、すべての要素の削除の問題を解決する、逆方向にループするバリアントが見つかりません。

モデルのコレクションを破壊する最もクリーンな方法として何を提案しますか?

ありがとう

4

7 に答える 7

34

古き良き時代の良いものを使うこともできますポップその場で破壊する:

var model;

while (model = this.collection.first()) {
  model.destroy();
}
于 2012-06-02T00:48:47.750 に答える
25

私も最近この問題に遭遇しました。あなたはそれを解決したように見えますが、なぜこれが起こっているのかを正確に疑問に思っている他の人にとっても、より詳細な説明が役立つかもしれないと思います。

では、実際に何が起こっているのでしょうか。

モデル(本)のコレクション(ライブラリ)があるとします。

例えば:

console.log(library.models); // [object, object, object, object]

それでは、最初のアプローチを使用して、すべての本を調べて削除しましょう。

library.each(function(model) {
  model.destroy();
});

eachBackboneコレクションに混合されているアンダースコアメソッドです。モデルへのコレクション参照(library.models)を、これらのさまざまなアンダースコアコレクションメソッドのデフォルト引数として使用します。もちろん。それは合理的に聞こえます。

これで、モデルがを呼び出すとdestroy、コレクションでも「破棄」イベントがトリガーされ、モデルへの参照が削除されます。内部removeでは、これに気付くでしょう:

this.models.splice(index, 1);

に慣れていない場合は、ドキュメントspliceを参照してください。もしそうなら、なぜこれが問題になるのかがわかるかもしれません。

実証するためだけに:

var list = [1,2];
list.splice(0,1); // list is now [2]

これにより、each経由するモデルオブジェクトへの参照がmodels動的に変更されるため、ループは要素をスキップします。

ここで、JavaScript <1.6を使用している場合、次のエラーが発生する可能性があります。

Uncaught TypeError: Cannot call method 'destroy' of undefined

これは、のアンダースコア実装では、ネイティブが欠落eachしている場合、それ自体の実装にフォールバックするためです。forEach存在しない要素にアクセスしようとするため、反復の途中で要素を削除すると文句を言います。

ネイティブforEachが存在する場合は、代わりにそれが使用され、エラーはまったく発生しません。

なんで?ドキュメントによると:

配列の既存の要素が変更または削除された場合、コールバックに渡されるそれらの値は、forEachがそれらにアクセスしたときの値になります。削除された要素は訪問されません

それで、解決策は何ですか?

collection.eachコレクションからモデルを削除する場合は使用しないでください。モデルへの参照を含む新しい配列で作業できるようにするメソッドを使用します。clone1つの方法は、アンダースコアメソッドを使用することです。

_.each(_.clone(collection.models), function(model) {
  model.destroy();
});
于 2014-02-25T19:37:32.897 に答える
13

私はここで少し遅れていますが、これもかなり簡潔な解決策だと思います。

_.invoke(this.collection.toArray(), 'destroy');
于 2013-07-18T00:46:21.770 に答える
1

ショーンアンダーソンの答えに便乗。バックボーンコレクション配列に直接アクセスできるので、このようにすることができます。

_.invoke(this.collection.models, 'destroy');

またはreset()、パラメータなしでコレクションを呼び出すだけdestroyで、そのコレクション内のモデルのmetodがバイトリガーされます。

this.collection.reset(); 

http://backbonejs.org/#Collection-models

于 2013-12-25T23:44:08.073 に答える
0

これは機能しますが、アンダースコアを使用できないことに少し驚いています。

for (var i = this.collection.length - 1; i >= 0; i--)
    this.collection.at(i).destroy();
于 2012-06-02T00:45:50.997 に答える
0

特に、各モデルでdestroyを呼び出し、コレクションをクリアDELETEし、サーバーを呼び出さない必要がある場合は、この方法をお勧めします。idまたはidAttributeに設定されているものを削除することで、それが可能になります。

var myCollection = new Backbone.Collection();
var models = myCollection.remove(myCollection.models);
_.each(models, function(model) {
  model.set('id', null); // hack to ensure no DELETE is sent to server
  model.destroy();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>

于 2016-06-29T06:30:03.597 に答える
0

forこのためにアンダースコアやループは必要ありません。

this.collection.slice().forEach(element => element.destroy());
于 2019-07-30T07:43:52.200 に答える