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

发布于 2024-12-20 07:31:20 字数 1876 浏览 0 评论 0 原文

警告:代码位于 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() 填充它之间存在一些细微的区别。该对象在脚本调试窗口中看起来不错,但并不令人高兴。

那么,这里发生了什么事,我是否走在正确的轨道上?

谢谢

Warning: Code is in Coffeescript. I hope that's ok.

I have a model, Song, a collection Songs, and a view SongsView. Here it is:

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)

The issue I'm having is that there is some subtle difference between initializing songs from the JSON string and allowing backbone to populate it using fetch(). The object looks ok in the script debug window, but no joy.

So, what's going on here and am I sort of on the right track?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南…巷孤猫 2024-12-27 07:31:20

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

您可能应该在实例化视图的下方添加您的ongs.fetch。

Fetch is an asynchronous method, this means that when you render your view, the data has not been retrieved, but when you write it manually, the data is there. The general way to do this is to bind the reset trigger that gets called by fetch to the render method.

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

You should probably more your songs.fetch below where you instantiate your view too.

天邊彩虹 2024-12-27 07:31:20

正如 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/

As answered by Gazler, the problem is that fetch is asynchronous. If you want to use Gazler's solution, be aware that the collection's fetch method no longer triggers the reset event by default. Therefore, you'll need to have the collection explicitly trigger the reset event:

my_collection.fetch({reset: true})

Another solution to solving this is using jQuery deferreds to display the view once the results have been fetched. More one using deferreds to manage view display when fetching data asynchronously: http://davidsulc.com/blog/2013/04/01/using-jquery-promises-to-render-backbone-views-after-fetching-data/

And waiting for multiple asynchronous data sources to return: http://davidsulc.com/blog/2013/04/02/rendering-a-view-after-multiple-async-functions-return-using-promises/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文