2017-01-11 11 views
2
myView = Backbone.View.extend({ 
    //event binding etc etc 

    render: function() { 
     //render some DOM 
    } 
}) 

anotherView = Backbone.View.extend({ 
    events: { 
     'click .selector doThis' 
    }, 

    createNewView: function() { 
     var view = new myView(); 
    } 
}) 

createNewViewは複数回呼び出すことができます。私の理解では、変数viewは、createNewView関数が完了したときにまだ存在するオブジェクト/コードを参照するため、JavaScriptの組み込みのガベージコレクションによって必ずしも削除されるとは限りません。Backbone.jsで子ビューをインスタンス化するときのメモリリークを回避する方法

これは間違いありませんか?これに対処する方法は?

myApp.view = new myView() 

次にcreateNewViewに、私はちょうどこの上でレンダリングを呼び出す:

私の現在のアプローチは、私のアプリのレベルで一度myViewを初期化することで基本的に

myApp.view.render() 

、私は今まで1を持っていますそれらの私はそれを再使用します。

代わりのアプローチは、アレイ内のサブビューの作成を追跡し、次にそれらがもはや必要ではないとわかったときに順番にそれぞれ.remove()を呼び出します。

私は適切なトラックにいますか?

myViewlistenToで他のオブジェクトにバインドされたコールバックを作成した場合、それらは変数を再割り当てするだけでは削除されないため、2番目のアプローチが優れています。つまり、newを呼び出してビューの新しいインスタンスをインスタンス化する場合、最初に破棄されたインスタンスにremove()を呼び出す必要があります。

答えて

4

例では、ビューelをDOMに入れないので、ビューを参照するものは何もないので、ガベージコレクションによって収集されます。

ビューに何もバインドされていないことを確認するには、.remove()と呼ぶことをお勧めします。です。それは削除されます:

  • DOMからの眺めのel
  • jQueryのDOMイベント
  • バックボーンイベントリスナーが

バックボーン.remove source

// Remove this view by taking the element out of the DOM, and removing any 
// applicable Backbone.Events listeners. 
remove: function() { 
    this._removeElement(); 
    this.stopListening(); 
    return this; 
}, 

// Remove this view's element from the document and all event listeners 
// attached to it. Exposed for subclasses using an alternative DOM 
// manipulation API. 
_removeElement: function() { 
    this.$el.remove(); 
}, 

に(ほぼすべての他の回答ではと私)mu is too short in the commentsで述べたように、あなたは常にfavor listenTo over on or bindメモリリークを回避し、アンバインドイベントを容易にする必要があります。

親ビュー内にネストされた子ビューをレンダリングする場合は、子ビューの配列を後で.remove()を呼び出すように保つことをお勧めします。

単純なリストビューは次のようになります。

var ListView = Backbone.View.extend({ 
    initialize: function() { 
     // Make an array available to keep all the child views 
     this.childViews = []; 
    }, 
    addOne: function(model) { 
     var view = new Backbone.View({ model: model }); 

     // as you create new views, keep a reference into the array. 
     this.childViews.push(view); 

     this.$el.append(view.render().el); 
    }, 

    renderList: function() { 
     // replace the view content completely with the template 
     this.$el.html(this.templates()); 

     // then cleanup 
     this.cleanup(); 

     // then render child views 
     this.collection.each(this.addOne, this); 

     return this; 
    }, 

    cleanup: function() { 
     // quick way to call remove on all views of an array 
     _.invoke(this.childViews, 'remove'); 
     // empty the array 
     this.childViews = []; 
    }, 
}); 

他のオブジェクトがそれを聞いている場合は、それが収集されず、リークかもしれませんが。参照を追跡し、不要になった時点で参照をすべて削除することが重要です。

+1

これは、 'on 'ではなく' listenTo'を使用し、すべてを 'off'よりも' stopListening'するほうが簡単な理由です。 –

+0

ありがとうございます。 _.invokeメソッドは、私の_eachループよりも簡単な方法です。 –

関連する問題