3

DOM要素が削除された後にメモリに残るという問題があります。以下に示す例を設定しました。ビュー(およびjQuery)を管理するためにバックボーンレイアウトマネージャープラグインを使用していることに注意してください。

リスト内のアイテムの1つを削除する前後に、Chromeでヒープスナップショットを作成し、2つを比較しました。

Chromeヒープスナップショットの比較

ご覧のとおり、LI要素はまだメモリ内にあります。

バックボーンレイアウトマネージャーは、ビューが削除されたときにview.unbind()とview.stopListening()を呼び出します。

以下はサンプルコードです。

ListOfViewsToDelete.js

var TestModel = Backbone.Model.extend({
  });

  var TestCollection = Backbone.Collection.extend({
    model: TestModel,
  });

  var ViewToDelete = Backbone.View.extend({
    template: "ViewToDelete",
    tagName: "li",
    events: {
      "click .delete-button": "deleteItem"
    },
    deleteItem: function() {
      this.$el.trigger('remove-item', [this.model.id]);
    }
  });

  var ListOfViewsToDelete = Backbone.View.extend({
    template: "ListOfViewsToDelete",
    initialize: function() {
      this.collection = new TestCollection();

      for (var i = 0; i < 5; i++) {
        this.collection.add(new TestModel({id: i}));
      }

      this.listenTo(this.collection, 'all', this.render);
    },
    events: {
      "remove-item": "removeItemFromCollection"
    },
    beforeRender: function() {

      this.collection.each(function(testModel) {
        this.insertView("ul", new ViewToDelete({
          model: testModel
        }));
      }, this);

    },
    removeItemFromCollection: function(event, model) {
      this.collection.remove(model);
    }
  });

router.js

app.useLayout("MainLayout").setViews({
                    "#main": new ListOfViewsToDelete()
                }).render();

ListOfViewsToDelete.html

<ul>
</ul>

ViewToDelete.html

View to delete
<button class="delete-button">x</button>
4

1 に答える 1

4

コードにはいくつかの問題があります。

  • イベントthis.$elをトリガーするモデルとして使用します。remove-item代わりにモデルを使用する必要があります。

  • ビューは、モデルからのイベントが自分自身を削除するタイミングを知るのを待つ必要があります。

これが私が思いついたコードです。うまくいかない場合は、自分で実行できるようにコードをどこかに投稿してください。

var ViewToDelete = Backbone.View.extend({
    テンプレート: "ViewToDelete"、

    tagName: "li"、

    イベント:{
      ".delete-buttonをクリック": "deleteItem"
    }、

    初期化:関数(){
      this.listenTo(this.model、'remove'、this.remove);
    }、

    deleteItem:function(){
      this.model.remove();
    }
});

デフォルトの実装は、モデルview.remove()を削除this.$elしてリッスンを停止します。

削除:function(){
  this。$el.remove();
  this.stopListening();
  これを返します。
}、

編集:コードをオンラインで投稿していただきありがとうございます。これが私が起こっていると思うことです(私は将来の視聴者のためにも文書化しています)。

スナップショットを作成し、分離されたDOMツリーでフィルター処理すると、次のように表示されます。

Webインスペクタースナップショット

重要な部分は保持ツリーです。つまり、LIが削除されないようにする参照です。唯一の重要なことはsizzle-1364380997635です。それはあなたのコードから来ているのではなく、実際にはjQueryから、より具体的にはそのSizzleエンジンから来ています。キーはここから来ます:

https://github.com/jquery/sizzle/blob/master/sizzle.js#L33

コードをさらに見ると、キャッシュがあることがわかります。

https://github.com/jquery/sizzle/blob/master/sizzle.js#L1802

つまり、一言で言えば、コードはリークしませんが、jQueryには、とにかく削除されないようにする内部キャッシュがあります。このキャッシュには数十個の要素しか含めることができないため、要素を永久に保持することはありません。

于 2013-03-26T17:52:58.537 に答える