事件仍然绑定到僵尸实例

时间:2012-05-28 16:57:42

标签: javascript memory-leaks backbone.js marionette

我面对看起来像僵尸参考案例。

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

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

相反,可以找到控制器here

操作流程如下:

  1. 管理员在点击呼叫" manageUsers"的路线时访问用户列表。在控制器上。
  2. 管理员点击用户行和事件"用户:已选择"触发并且侦听器接收用户实例以使用。
  3. DetailsLayout在应用程序的主要布局中实例化并呈现。特别 在其内容"区域。
  4. 处理用户详细信息表单的视图也会被实例化并在内部呈现 DetailsLayout" dettagli"区域。
  5. 此时,管理员有兴趣管理此用户的笔记。所以他点击了 在标有"注释"的标签上并且注释列表在DetailsLayout" note"中呈现。区域。
  6. 点击管理员想要使用的备注即可触发事件"备注:已选择"它将note实例传递给适当的事件处理程序(DetailsLayout.showNote)。
  7. 此时管理员点击触发DetailsLayout.showUsers的链接,然后触发事件" users:index"他听了上述控制人的意见 回到上面列表的第1点。

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

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

    上面的代码显示,每次显示用户的详细信息时,都会创建一个新的DetailsLayout实例。难道这不足以保证周围没有僵尸吗?如果我从backbone.marionette文档中正确回忆起来,每次layout.region.show()被点击时,它会关闭上一个视图(解除绑定事件和所有其他视图)并附加新传递的视图。

    我做错了什么?

    提前感谢您的帮助。 此致

    P.S。

    Backbone.marionette版本为0.8.4

    Backbonejs版本是0.9.2

1 个答案:

答案 0 :(得分:2)

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,包括使用{{1} },bindTo