以前,我的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练习吗?不确定是否有更好的方法。
答案 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)