Backbone + Rails集合获取

时间:2012-04-03 20:06:01

标签: ruby-on-rails backbone.js

以前,我的Backbone路由器看起来像这样:

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(即输入网址),则不会呈现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)

哪个工作正常。但是,显然有一点延迟,因为每次切换路由时都会重新获取集合。这是一个很好的Backbone练习吗?不确定是否有更好的方法。

1 个答案:

答案 0 :(得分:6)

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

只需创建一个Deferred对象并将其附加到路由器即可。然后在initialize方法中获取集合并在Deferred对象上调用resolve()。您的索引和show方法可以订阅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)