以前,我的主干路由器是这样的:
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)