【问题标题】:event stays bound to zombie instance事件保持绑定到僵尸实例
【发布时间】:2012-05-28 16:57:42
【问题描述】:

我正面临一个看起来像僵尸参考案例的情况。

首先,这是我正在使用的代码。

在这里您可以找到我的用户详细信息管理器布局gist

可以找到控制器 here

操作流程如下:

  1. 管理员在点击控制器上调用“manageUsers”的路由时访问用户列表。
  2. 管理员单击用户行并触发“users:selected”事件,并且侦听器接收要使用的用户实例。
  3. DetailsLayout 被实例化并呈现在应用程序的主布局中。具体来说 在其“内容”区域中。
  4. 处理用户详细信息表单的视图也被实例化并在内部呈现 DetailsLayout 的“dettagli”区域。
  5. 此时,管理员有兴趣管理此用户的笔记。所以他点击 在标签为“notes”的选项卡上,notes 列表将呈现在 DetailsLayout“note”区域中。
  6. 单击管理员想要使用的注释会触发事件“notes:selected”,该事件会将注释实例传递给相应的事件处理程序 (DetailsLayout.showNote)。

此时,一旦管理员单击触发 DetailsLayout.showUsers 的链接,该链接又触发上述控制器监听的事件“users:index”,他 回到上面列表的第 1 点。

重复整个过程直到第 5 点按预期工作,但只要管理员 选择要工作的注释调试器显示有关未定义 DetailsLayout 区域“注释”的错误。

逐步运行代码我发现在第二次运行时触发的事件是 正确绑定到 DetailsLayout 的正确实例,但第 6 点仍绑定到第一次传递时使用的实例。

上面的代码表明,每次显示用户的详细信息时,都会创建一个新的 DetailsLayout 实例。难道这还不足以保证没有僵尸还在附近吗?如果我从backbone.marionette 文档中没记错的话,每次layout.region.show() 被击中时,它都会关闭前一个视图(解除绑定事件和所有其他事件)并附加新的passwed 视图。

我做错了什么?

提前感谢您的帮助。 问候

附言

Backbone.marionette 版本为 0.8.4

Backbonejs 版本为 0.9.2

【问题讨论】:

  • 您可以在问题中发布您的代码吗?

标签: javascript memory-leaks backbone.js marionette


【解决方案1】:

您在 UserDetailsList 中的构造函数是问题所在:

            constructor: (@user) ->
                console.addHistory("DetailsLayout","INIT")
                super()
                Hub.vent.on("notes:selected",(note) => @showNote(note))
                Hub.vent.on("notes:show", => @showNotes())
                Hub.vent.on("notes:save", (note) => @saveNote(note))
                Hub.vent.on("notes:delete", (note) => @deleteNote(note))
                Hub.vent.on("notes:new", => @showNote(new Note()))

您直接绑定到Hub.vent,但从未明确解除与这些事件的绑定。因此,您的 UserDetails 列表实例将永远存在于内存中。

要解决此问题,您应该使用布局的 bindTo 方法,该方法将跟踪绑定并在调用布局的 close 方法时为您解除绑定。

            constructor: (@user) ->
                console.addHistory("DetailsLayout","INIT")
                super()
                @bindTo(Hub.vent, "notes:selected",(note) => @showNote(note))
                @bindTo(Hub.vent, "notes:show", => @showNotes())
                @bindTo(Hub.vent, "notes:save", (note) => @saveNote(note))
                @bindTo(Hub.vent, "notes:delete", (note) => @deleteNote(note))
                @bindTo(Hub.vent, "notes:new", => @showNote(new Note()))

当您不再需要布局时,请务必正确关闭它。在布局实例上调用 close 方法。这将正确清除构造函数设置的所有bindTo 事件。

仅供参考 - Layout 直接从 ItemView 扩展,因此有关 ItemView 的所有信息/文档也适用于 Layout,包括使用 bindToclose 等。

【讨论】:

  • 嗨德里克!再次感谢你的帮助。您在代码中看到的 Hub 是 Backbone.Marionette.Application 的子类。我相信我必须审查事件发布/订阅系统集中化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
  • 2012-03-19
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
相关资源
最近更新 更多