Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Backbone.js导航工作一次,但不能再次工作_Backbone.js_Coffeescript - Fatal编程技术网

Backbone.js导航工作一次,但不能再次工作

Backbone.js导航工作一次,但不能再次工作,backbone.js,coffeescript,Backbone.js,Coffeescript,我正在使用rails上的主干gem中的Backbone.js 0.9.2。我还尝试使用新的“pushState”而不是旧的散列URL 问题 我正在构建一个类似于CRUD的标准Rails界面来跟踪我的约会。我在主index.jst.eco页面上有一个“新”链接: <h1>Appointments</h1> <p><a href="/appointments/new" class="new">New Appointment</a></

我正在使用rails上的主干gem中的Backbone.js 0.9.2。我还尝试使用新的“pushState”而不是旧的散列URL

问题

我正在构建一个类似于CRUD的标准Rails界面来跟踪我的约会。我在主index.jst.eco页面上有一个“新”链接:

<h1>Appointments</h1>
<p><a href="/appointments/new" class="new">New Appointment</a></p>
然后调用主干路由器:

class BackboneOnRails.Routers.Appointments extends Backbone.Router
  routes:
    '': 'index'
    'appointments': 'index'
    'appointments/new': 'new'

  initialize: ->
    this.appointments = new BackboneOnRails.Collections.Appointments()
    this.appointmentsIndexView = new BackboneOnRails.Views.AppointmentsIndex({collection: this.appointments})
    this.appointmentsIndexView.render()

  index: ->
    $("#container").html(this.appointmentsIndexView.el)
    this.appointments.fetch()

  new: ->
    appointments = new BackboneOnRails.Collections.Appointments()
    view = new BackboneOnRails.Views.AppointmentNew({collection: appointments})
    $("#container").html(view.render().el)
当我点击浏览器后退按钮,然后再次尝试使用“新建”链接时,问题就出现了。这一次,它会完全重新加载页面

当我回击浏览器时,javascript绑定发生了什么变化


我有一个展示活动的项目,我可以去来回没有问题。我将两者进行了比较,它们看起来像是相同类型的调用。

问题在于您试图重新使用appointmentsIndexView实例。从DOM中删除视图会破坏DOM事件处理程序。将视图的
el
重新添加到DOM不会重新连接它们

问题概述 当您第一次使用路由器的
initialize
index
方法加载该视图时,一切正常,因为您有一个新的IndexView实例。DOM事件被正确地附加到视图中,生活是美好的

当您点击路由器的
new
route/method时,您实际上是在试图从屏幕上删除索引视图,并将其替换为addnew视图。这是从视觉角度和“添加新视图”的角度进行的

但是,当您点击后退按钮时,您将停留在浏览器选项卡中的同一个实时应用程序实例中。在启用pushstate的情况下点击back按钮,告诉浏览器不要重新加载整个应用程序,只需更新url并启动索引的router方法即可

在这种情况下,您会发现索引视图不是从头开始重新构建的。您使用的是同一个视图实例,但从服务器重新加载数据。数据加载工作得非常好,因为您的视图和集合仍处于连接状态。但是,DOM事件绑定失败,因为它们的绑定以前已被删除,而没有重新添加

2共同解决方案 有两种常见的解决方案,以及这些解决方案的许多变体

1) 不要重复使用视图实例。 这是我强烈推荐的建议。在我尝试重用视图实例的每一个实例中,我都会遇到非常大的问题,包括您遇到的确切问题

而是在每次需要显示约会索引时重新创建一个新的视图实例。这意味着您可以在路由器的
index
方法中创建新的索引视图,而不是
initialize
方法

2) 清除并重新绑定DOM事件 如果出于某种原因,您觉得确实需要重新使用view实例(这永远不会是真的),您可以使用Tim Branyen不久前在其博客上发布的一些信息来解决这个问题:

我不推荐这种方法。立即重新使用视图实例似乎是个好主意,但它会导致其他问题的出现,包括在应用程序中留下太多未使用的部分导致内存使用过多

旁注:僵尸和内存泄漏 在这两种情况下,无论您是决定重用视图实例还是在需要时重新创建它们,您都可能会遇到一些内存泄漏

在重复使用视图的情况下,您在不需要时显式地保留内存中的对象。这不是真正的“泄漏”,而是内存的过度使用。您应该在不需要时取消引用对象,并在需要时重新创建它。这将减少内存使用,让你的应用程序运行得更好

我在这里发布了一篇博客文章,介绍了这是如何工作的:

在不重用视图的情况下,从可见DOM中删除视图后,可能会留下模型和集合事件绑定,从而导致真正的内存泄漏。如果决定不重复使用视图,则需要使替换
#容器的代码更加健壮,并让它清理旧视图


我有一篇博客文章详细介绍了解决方案:-一定要阅读Johnny Oshika在这篇文章中的评论,因为他指出了一个非常有用的StackOverflow答案,其中他展示了一种处理模型和收集事件的简单方法。

问题在于您试图重新使用appointmentsIndexView实例。从DOM中删除视图会破坏DOM事件处理程序。将视图的
el
重新添加到DOM不会重新连接它们

问题概述 当您第一次使用路由器的
initialize
index
方法加载该视图时,一切正常,因为您有一个新的IndexView实例。DOM事件被正确地附加到视图中,生活是美好的

当您点击路由器的
new
route/method时,您实际上是在试图从屏幕上删除索引视图,并将其替换为addnew视图。这是从视觉角度和“添加新视图”的角度进行的

但是,当您点击后退按钮时,您将停留在浏览器选项卡中的同一个实时应用程序实例中。在启用pushstate的情况下点击back按钮,告诉浏览器不要重新加载整个应用程序,只需更新url并启动索引的router方法即可

在这种情况下,您会发现索引视图不是从头开始重新构建的。您使用的是同一个视图实例,但从服务器重新加载数据。数据加载工作得非常好,因为您的视图和集合仍处于连接状态。但是,DOM事件绑定失败,因为它们的绑定以前已被删除,而没有重新添加

2共同解决方案 对于这一点,有两种常见的解决方案,还有许多不同的解决方案
class BackboneOnRails.Routers.Appointments extends Backbone.Router
  routes:
    '': 'index'
    'appointments': 'index'
    'appointments/new': 'new'

  initialize: ->
    this.appointments = new BackboneOnRails.Collections.Appointments()
    this.appointmentsIndexView = new BackboneOnRails.Views.AppointmentsIndex({collection: this.appointments})
    this.appointmentsIndexView.render()

  index: ->
    $("#container").html(this.appointmentsIndexView.el)
    this.appointments.fetch()

  new: ->
    appointments = new BackboneOnRails.Collections.Appointments()
    view = new BackboneOnRails.Views.AppointmentNew({collection: appointments})
    $("#container").html(view.render().el)