首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Backbone.js中处理视图和模型对象

在Backbone.js中处理视图和模型对象
EN

Stack Overflow用户
提问于 2011-09-11 23:30:32
回答 3查看 35.8K关注 0票数 64

在不需要时处置模型/视图实例的最有效方法是什么?

通常,我将所有逻辑放在控制器/路由器中。它决定了应该创建什么视图,以及应该向它们提供什么模型。通常,有几个处理程序函数,对应于不同的用户操作或路由,每次执行处理程序时,我都会在其中创建新的视图实例。当然,这应该会消除我之前存储在视图实例中的所有内容。然而,在某些情况下,一些视图保留了DOM事件处理程序本身,并且它们没有正确地解除绑定,这导致这些实例保持活动状态。我希望如果有一种适当的方法来销毁视图实例,例如,当它们的el (DOM表示)被分离或被抛出DOM时

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-12 11:28:31

你走在正确的道路上。您应该有一个控制视图生命周期的对象。我不喜欢把这个放在我的观点中。我喜欢为此创建一个单独的对象。

你需要做的就是在必要的时候解除事件的绑定。为此,最好在所有视图上创建一个" close“方法,并使用控制所有内容的生命周期的对象始终调用close方法。

例如:

代码语言:javascript
复制
  function AppController(){
    this.showView = function (view){
      if (this.currentView){
        this.currentView.close();
      }
      this.currentView = view;
      this.currentView.render();
      $("#someElement").html(this.currentView.el);
    }
  }

此时,您可以将代码设置为只有一个AppController实例,并且始终从路由器或需要在屏幕的#someElement部分显示视图的任何其他代码中调用appController.showView(...)

(我有另一个非常简单的骨干应用程序的例子,它使用"AppView“(运行应用程序主要部分的骨干视图),这里:http://jsfiddle.net/derickbailey/dHrXv/9/ )

默认情况下,视图上不存在close方法,因此您需要为每个视图自己创建一个。close方法中应该始终包含两个东西:this.unbind()this.remove()。除此之外,如果您要将视图绑定到任何模型或集合事件,则应该在close方法中取消绑定它们。

例如:

代码语言:javascript
复制
  MyView = Backbone.View.extend({
    initialize: function(){
      this.model.bind("change", this.modelChanged, this);
    },

    modelChanged: function(){
      // ... do stuff here
    },

    close: function(){
      this.remove();
      this.unbind();
      this.model.unbind("change", this.modelChanged);
    }
  });

这将正确地清除DOM中的所有事件(通过this.remove())、视图本身可能引发的所有事件(通过this.unbind())以及视图从模型绑定的事件(通过this.model.unbind(...))。

票数 77
EN

Stack Overflow用户

发布于 2013-02-25 06:54:07

一种更简单的方法是在Backbone.View对象上添加自定义close方法

代码语言:javascript
复制
Backbone.View.prototype.close = function () {
  this.$el.empty();
  this.unbind();
};

使用上面的代码,您可以执行以下操作

代码语言:javascript
复制
var myView = new MyView();

myView.close();

很简单。

票数 13
EN

Stack Overflow用户

发布于 2013-09-29 12:52:34

我总是对视图进行核化,有时还会重用模型。如果您保留模型,那么确保视图被释放可能是一件痛苦的事情。如果模型没有正确解除绑定,则它们可能会保留对视图的引用。

在Backbone ~0.9.9版本中,使用view.listenTo()而不是model.on()绑定模型允许通过控制反转(视图控制绑定而不是模型)进行更容易的清理。如果使用view.listenTo()进行绑定,则对view.stopListening()或view.remove()的调用将删除所有绑定。类似于调用model.off(null,null,this)。

我喜欢通过使用close函数半自动调用子视图来扩展视图来清理视图。子视图必须由父视图的属性引用,或者必须添加到父视图中名为childViews[]的数组中。

下面是我使用的close函数。

代码语言:javascript
复制
// fired by the router, signals the destruct event within top view and 
// recursively collapses all the sub-views that are stored as properties
Backbone.View.prototype.close = function () {

    // calls views closing event handler first, if implemented (optional)
    if (this.closing) {
        this.closing();  // this for custom cleanup purposes
    }

    // first loop through childViews[] if defined, in collection views
    //  populate an array property i.e. this.childViews[] = new ControlViews()
    if (this.childViews) {
        _.each(this.childViews, function (child) {
            child.close();
        });
    }

    // close all child views that are referenced by property, in model views
    //  add a property for reference i.e. this.toolbar = new ToolbarView();
    for (var prop in this) {
        if (this[prop] instanceof Backbone.View) {
            this[prop].close();
        }
    }

    this.unbind();
    this.remove();

    // available in Backbone 0.9.9 + when using view.listenTo, 
    //  removes model and collection bindings
    // this.stopListening(); // its automatically called by remove()

    // remove any model bindings to this view 
    //  (pre Backbone 0.9.9 or if using model.on to bind events)
    // if (this.model) {
    //  this.model.off(null, null, this);
    // }

    // remove and collection bindings to this view 
    //  (pre Backbone 0.9.9 or if using collection.on to bind events)
    // if (this.collection) {
    //  this.collection.off(null, null, this);
    // }
}

然后声明一个视图,如下所示。

代码语言:javascript
复制
views.TeamView = Backbone.View.extend({

    initialize: function () {
        // instantiate this array to ensure sub-view destruction on close()
        this.childViews = [];  

        this.listenTo(this.collection, "add", this.add);
        this.listenTo(this.collection, "reset", this.reset);

        // storing sub-view as a property will ensure destruction on close()
        this.editView = new views.EditView({ model: this.model.edits });
        $('#edit', this.el).html(this.editView.render().el);
    },

    add: function (member) {
        var memberView = new views.MemberView({ model: member });
        this.childViews.push(memberView);    // add child to array

        var item = memberView.render().el;
        this.$el.append(item);
    },

    reset: function () {
        // manually purge child views upon reset
        _.each(this.childViews, function (child) {
            child.close();
        });

        this.childViews = [];
    },

    // render is called externally and should handle case where collection
    // was already populated, as is the case if it is recycled
    render: function () {
        this.$el.empty();

        _.each(this.collection.models, function (member) {
            this.add(member);
        }, this);
        return this;
    }

    // fired by a prototype extension
    closing: function () {
        // handle other unbinding needs, here
    }
});
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7379263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档