更改视图的模型时,更换模型或创建新视图更好吗?

时间:2011-07-28 12:46:08

标签: backbone.js

我的Backbone应用程序中有一个电子邮件视图。它目前在我的控制器的view操作中实例化。它有点像这样:

routes: {
  'email/:id': email
},

//...

email: function (id) {
  var email = new Email({
    id: id
  });
  this.emailView = new EmailView({
    model: email
  });
  email.fetch();
}

现在,问题是,如果我访问一封电子邮件,那么我最终会创建两个单独的EmailView。这意味着,例如,EmailView中的删除链接绑定到两个单独的Email模型,因此单击删除将删除两者(不是一件好事)。

我正在寻找两种解决方案。在其中一个,我将缓存EmailView,并更新其模型。那么问题是我必须重新绑定events中的EmailView

另一种解决方案是像我现在一样创建一个新的EmailView,但在替换它之前解除旧的EmailView.el事件的绑定。

我是以正确的方式来做这件事的吗?有没有更好的方法来处理这种情况?提前干杯。

3 个答案:

答案 0 :(得分:3)

为每个模型实例创建单独的视图实例。每次您访问新电子邮件时,都会丢弃旧视图并使用新的电子邮件实例创建新视图。

如果我猜的是你左边的列表视图和右边的编辑器,你可能拥有的东西。您可以从左侧列表中选择电子邮件,并希望电子邮件正文显示在右侧。

你真的想要5个视图类。

PageView
    has_one EmailCollectionView on left
    has_one EmailEditorView on right

EmailCollectionView
    has_many EmailSummaryViews as vertical list

EmailEditorView
    has_one EmailView centered

当您在EmailCollectionView中单击时,您会触发一个事件 通过EmailEditorView获取,它抛弃了它的旧版EmailView 并呈现新版本的EmailView

无论如何

这样的东西

答案 1 :(得分:2)

每当有人导航到例如,我们最初都会创建新的视图对象。 “候选人/节目”,就像电子邮件示例一样。该视图将处理程序绑定到其持久性模型的“重置”事件。当我们从命令行重置该模型时,我们会看到与该视图的实例一样多的事件。换句话说,即使添加到DOM中的元素都被完全破坏,该视图也不会被垃圾收集。

我们的解决方案是确保一次实例化我们的顶级视图,然后让他们在初始化方法中创建子视图。然后根据需要重新渲染它们。然后你不必担心垃圾收集的复杂性(就我从实验中可以看出,无论如何都不会发生)。

答案 2 :(得分:2)

我认为应该通过调用视图的remove()方法来删除DOM事件处理程序 - 请参阅http://api.jquery.com/remove(Backbone调用的内容)

如果重写remove()方法以删除对JohnnyO建议的任何模型事件的绑定,则垃圾收集应该负责删除视图。

我最终覆盖了remove()方法来处理这个问题:

class EmailView extends Backbone.View
    initialize: () ->
        @model.bind('change', @render)
    render: () =>
        # do some stuff
    remove: () ->
        @model.unbind('change', @render)
        super()

然后您可以在路由器中使用:

    routes:
      'email/:id': email

    //...

    email: (id) ->
      var email = new Email({
        id: id
      });
      this.emailView.remove() if this.emailView 
      this.emailView = new EmailView({
        model: email
      });
      email.fetch();
    }

这将假设视图中的所有事件都绑定到正确的元素 - 也就是说,您在视图中使用@el(或this.el)并且每个视图都有自己的@ el / this .el。