javascript - 在 Backbone.js 中实例化 subview 时如何避免内存泄漏

标签 javascript backbone.js

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不一定会被 JavaScript 的内置垃圾回收删除,因为它引用了 createNewView 时仍然存在的对象/代码。功能完成。

这是正确的吗?怎么处理这个问题?

我当前的方法是初始化myView一旦达到我的应用程序级别:

myApp.view = new myView()

然后在 createNewView我只是对此调用渲染:

myApp.view.render()

本质上,我只拥有其中一个,而且我会重复使用它。

另一种方法是跟踪数组中 subview 的创建,然后我调用 .remove()当我知道不再需要它们时,依次对每一个进行处理。

我走在正确的道路上吗?

我认为第二种方法更好,因为如果 myView使用 listenTo 在其他对象上创建绑定(bind)回调,这些不会简单地通过重新分配变量来删除。也就是说,如果我打电话 new要实例化 View 的新实例,我应该调用 remove()首先是关于被丢弃的实例......看来。

最佳答案

在您的示例中,您没有将 View 的 el 放入 DOM,因此没有任何内容引用该 View ,然后它将被垃圾收集器收集。

确保 View 不再绑定(bind)到某些内容的一件好事是调用 .remove()就在上面。它将删除:

  • 来自 DOM 的 View 的 el
  • jQuery DOM 事件
  • Backbone 事件监听器。

Backbone .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以避免内存泄漏并简化解除绑定(bind)事件。

渲染嵌套在父 View 中的 subview 时,一个好的做法是保留 subview 的数组,以便稍后对每个 subview 调用.remove()

一个简单的 ListView 可能如下所示:

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 = [];
    },
});

尽管如果其他对象正在监听它,它不会被收集并且可能是泄漏。跟踪引用并在不再需要时将其全部删除非常重要。

关于javascript - 在 Backbone.js 中实例化 subview 时如何避免内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41595213/

相关文章:

node.js - 为什么 Grunt 会失败?

javascript - 我正在制作图像板,但无法找出链接引用

javascript - 在 svg 元素上使用带有 d3.js 的 Angular ng-class

javascript - json_encode 在我的外部 javascript 中没有显示任何内容

javascript - 路由器中的双 View 渲染

javascript - Routing.navigate 与 document.location.hash

javascript - 为什么从 Backbone 中的自定义 BaseView 扩展时, 'events' 没有绑定(bind)到 View ?

javascript - 我有一个打开第二个模态的模态,如果打开然后关闭第二个则无法关闭第一个模态

javascript - jQuery 选择器中的简单 jQuery 语法和连接

javascript - 如何在 Backbone 模型中放置按钮?