backbone.js在集合上遇到fetch()时遇到问题

时间:2011-12-08 20:48:21

标签: javascript backbone.js coffeescript

警告:代码在Coffeescript中。我希望没问题。

我有一个模型,Song,一个集合Songs和一个视图SongsView。这是:

SONG_TEMPLATE = '''
  <table>
  {{#if songs.length }}
    {{#each songs}}
        <tr><td>{{ this.name }}</td><td>{{ this.duration }}</td></tr>
    {{/each}}
  {{/if}}
  </table>
'''

$ ->
  class Song extends Backbone.Model
    parse: (response) ->
      console.log "model parsing #{response}"
    #

  class Songs extends Backbone.Collection
    initialize: ->
      @model = Song
      @url   = "/songs/data"

    parse: (response) ->
      console.log "collection parsing"
      console.log response

  # This works. The JSON here was grabbed right out of the XHR response I got from the server and pasted into my code.

  songs = new Songs(
    [
      {"name":"Stray Cat Strut","rating":4,"duration":3},
      {"name":"Chinatown","rating":2,"duration":4.2},
      {"name":"Sultans of Swing","rating":3,"duration":5.4},
      {"name":"Pride & Joy","rating":3,"duration":3}
    ]
    )

  # This fails. It should be exactly the same as the above code, and indeed, the collection parsing takes place.
  # However, the view renders nothing.

  # songs = new Songs
  # songs.fetch()

  class SongsView extends Backbone.View
    initialize: ->
      @model = Song
      @render()

    render: =>
      console.log "render"
      console.log @collection
      template = Handlebars.compile(SONG_TEMPLATE)
      @template = template(songs: @collection.toJSON())
      console.log "template: #{@template}"
      $('#song-list').html @template

  songView = new SongsView(collection: songs)

我遇到的问题是,在从JSON字符串初始化songs和允许主干使用fetch()填充它之间存在一些细微差别。该对象在脚本调试窗口中看起来没问题,但没有快乐。

那么,这里发生了什么,我是否走上正轨?

由于

2 个答案:

答案 0 :(得分:3)

Fetch是一种异步方法,这意味着当您渲染视图时,尚未检索到数据,但是当您手动编写数据时,数据就在那里。执行此操作的一般方法是将fetch调用的重置触发器绑定到render方法。

class SongsView extends Backbone.View
  initialize: ->
    @model = Song
    @collection.bind("reset", @render)
  render: =>
    console.log "render"
    console.log @collection
    template = Handlebars.compile(SONG_TEMPLATE)
    @template = template(songs: @collection.toJSON())
    console.log "template: #{@template}"
    $('#song-list').html @template

你可能应该在你实例化你的视图的地方找到更多你的歌曲。

答案 1 :(得分:0)

正如Gazler所回答的,问题是fetch是异步的。如果您想使用Gazler的解决方案,请注意,默认情况下,集合的fetch方法不再触发reset事件。因此,您需要让集合明确触发reset事件:

my_collection.fetch({reset: true})

解决此问题的另一个解决方案是使用jQuery deferreds在获取结果后显示视图。在异步获取数据时,有更多人使用延迟来管理视图显示:http://davidsulc.com/blog/2013/04/01/using-jquery-promises-to-render-backbone-views-after-fetching-data/

等待多个异步数据源返回:http://davidsulc.com/blog/2013/04/02/rendering-a-view-after-multiple-async-functions-return-using-promises/