Backbone+Rails集合获取



以前,我的主干路由器是这样的:

class App.Routers.ThingsRouter extends Backbone.Router
  routes: '': 'index'
  routes: 'previews/:id': 'show'
  initialize: ->
    @collection = new App.Collections.ThingsCollection
    @collection.fetch
  index: ->
    view = new App.Views.ThingsIndex(collection: @collection)
    $('#app-container').html(view.render().el)
  show: (id) ->
    @model = @collection.get(id)
    view = new App.Views.ThingsShow(model: @model)
    $('#app-container').html(view.render().el)

当导航到http://localhost时,我会得到index视图的渲染,而当单击各个元素时,我就会得到show视图的渲染。但是,如果我直接转到http://localhost/things/1(即通过键入URL),则不会呈现show视图。我意识到这是因为视图是在@collection.fetch完成之前渲染的。我将我的路由器更改为:

class App.Routers.ThingsRouter extends Backbone.Router
  routes: '': 'index'
  routes: 'previews/:id': 'show'
  initialize: ->
    @collection = new App.Collections.ThingsCollection
  index: ->
    @collection.fetch success: =>
      view = new App.Views.ThingsIndex(collection: @collection)
      $('#app-container').html(view.render().el)
  show: (id) ->
    @collection.fetch success: =>
      that.model = that.collection.get(id)
      view = new App.Views.ThingsShow(model: @model)
      $('#app-container').html(view.render().el)

这很好用。然而,由于每次切换路由时都会重新获取集合,因此显然会有一点延迟。这是好的骨干训练吗?不确定是否有更好的方法。

这是jQuery的Deferred()方法的一个很好的用例。

只需创建一个Deferred对象并将其附加到路由器即可。然后在initialize方法中获取集合,并对Deferred对象调用resolve()。您的index和show方法可以订阅done回调并实例化视图。在提取集合之前,不会运行此done回调。如果它已经被提取,那么它会立即运行。

class App.Routers.ThingsRouter extends Backbone.Router
  routes: '': 'index'
  routes: 'previews/:id': 'show'
  initialize: ->
    @collectionFetched = new $.Deferred
    @collection = new App.Collections.ThingsCollection
    @collection.fetch success: ->
      @collectionFetched.resolve()
  index: ->
    that = this
    @collectionFetched.done ->
      view = new App.Views.ThingsIndex(collection: that.collection)
      $('#app-container').html(view.render().el)
  show: (id) ->
    that = this
    @collectionFetched.done ->
      that.model = that.collection.get(id)
      view = new App.Views.ThingsShow(model: that.model)
      $('#app-container').html(view.render().el)

最新更新