12

デタッチされた DOM ツリー内の何かを参照している変数を取得する方法を正確に把握しようとしています。問題を 2 つの単純なビューに切り分け、Chrome Dev Tools (比較ビュー) を使用して、分離されたノードを参照しているものを見つけようとしています。開発ツールの画像を添付しました...

Chrome 開発ツールのスナップショット

開発ツールの下部には、デタッチされた div が作成されたことelが示されています。HomeViewしかし、そこからどこへ行くべきかわかりません。

メモリ リークの特定に関するスタック オーバーフローの投稿やブログの投稿をたくさん読みましたが、まだこれを理解できません。Backbone が特にメモリ リークを引き起こす可能性が高いことを知っているので、「ゾンビを殺す」手法を実装しましたが、メモリ リークはまだ残っています。ここに私の見解があります:

ヘルプ ビュー

    // Generated by CoffeeScript 1.6.3
    (function() {
      var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

      define(['jquery', 'jquerymobile', 'underscore', 'backbone'], function($, Mobile, _, Backbone) {
        var HelpView, _ref;
        return HelpView = (function(_super) {
          __extends(HelpView, _super);

          function HelpView() {
            _ref = HelpView.__super__.constructor.apply(this, arguments);
            return _ref;
          }

          HelpView.prototype.initialize = function() {
            return _.bindAll(this, "render", "jqdisplay", "close");
          };

          HelpView.prototype.render = function() {
            $(this.el).html("Help View");
            return this;
          };

          HelpView.prototype.jqdisplay = function() {};

          HelpView.prototype.close = function() {
            console.log('THIS', this);
            console.log($(this.el)[0].parentNode);
            $(this.el)[0].parentNode.removeChild($(this.el)[0]);
            this.undelegateEvents();
            $(this.el).removeData().unbind();
            this.remove();
            this.unbind();
            Backbone.View.prototype.remove.call(this);
            return delete this;
          };

          return HelpView;

        })(Backbone.View);
      });

    }).call(this);

ホーム ビュー

    // Generated by CoffeeScript 1.6.3
    (function() {
      var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

      define(['jquery', 'jquerymobile', 'underscore', 'backbone'], function($, Mobile, _, Backbone) {
        var HomeView, _ref;
        return HomeView = (function(_super) {
          __extends(HomeView, _super);

          function HomeView() {
            _ref = HomeView.__super__.constructor.apply(this, arguments);
            return _ref;
          }

          HomeView.prototype.initialize = function() {
            return _.bindAll(this, "render", "jqdisplay", "close");
          };

          HomeView.prototype.render = function() {
            $(this.el).html("Home View");
            return this;
          };

          HomeView.prototype.jqdisplay = function() {};

          HomeView.prototype.close = function() {
            console.log('THIS', this);
            console.log($(this.el)[0].parentNode);
            $(this.el)[0].parentNode.removeChild($(this.el)[0]);
            this.undelegateEvents();
            $(this.el).removeData().unbind();
            this.remove();
            this.unbind();
            Backbone.View.prototype.remove.call(this);
            return delete this;
          };

          return HomeView;

        })(Backbone.View);
      });

    }).call(this);

...そして、ルーターのメソッドで各ビューの「閉じる」メソッドを呼び出します...

  MyRouter.prototype.showView = function(view) {
    console.log('THIS', this);
    console.log("next view", view);
    console.log(this.currentView);
    if (this.currentView) {
      console.log('closing the current view...', this.currentView);
      console.log('starting', $('[data-role="content"]').html());
      this.currentView.close();
      delete this.currentView;
      console.log('remaining', $('[data-role="content"]').html());
      console.log('should be empty', this.currentView);
    }
    this.currentView = view;
    this.currentView.render();
    $('[data-role="content"]').html(this.currentView.el);
    if (this.currentView.jqdisplay) {
      return this.currentView.jqdisplay();
    }
  };

リークのライブ デモはこちら: http://bit.ly/15xPrW7。リークを引き起こす動作は、メニューを使用して 2 つのページ間を移動することです。

どんな助けでも大歓迎です!ありがとうございました!

4

1 に答える 1

5

うーんコーヒースクリプト。

それはさておき、ページでjqueryを使用してメモリリークを探しているときはいつでも、jquery domキャッシュを無効にする必要があります。リンク先のサンプル サイトを簡単に試してみたところ、分離されたノードの一部がそのキャッシュにあることがわかりました。

$.expr.cacheLength = 1;

これはあまり文書化されていませんが、実際のリークがどこから来ているのかを突き止めるのに役立つはずです.

于 2014-02-26T05:09:16.290 に答える