【问题标题】:Backbone.js not iterating through collectionBackbone.js 不遍历集合
【发布时间】:2012-11-29 07:45:10
【问题描述】:

有点奇怪……

我有收藏:

class Store.Collections.Product extends Backbone.Collection

  url: '/api/products'

  model: Store.Models.Product  

与视图:

class Store.Views.Origin extends Backbone.View

  initialize: ->
    @collection = new Store.Collections.Product()
    @collection.fetch() 
    @model.bind('change:formatted', @render, this);
    @render()

  events:
    'change [name=origin]': 'setOrigin'

  el: =>
    @options.parent.$('.origin-input')[0]

  template: JST["backbone/templates/shapes/product"]

  render: ->
    $this = $(this.el)
    $this.html(@template(model: @model.toJSON(), errors: @model.errors))
    console.log(@collection)
    @collection.each(@appdenDropdown)
    @delegateEvents()
    this

  appdenDropdown: (product) ->
    console.log("append trigger")
    #view = new Store.Views.Products(model: product)
    #$('#history').append(view.render().el)

使用模板:

  <div id="history"></div>

该系列作品...

console.log(@collection)

显示数据!然而

@collection.each(@appdenDropdown)

不做任何事情,不出错,或通过任何事情。它只是没有做任何事情。我正在尝试从集合中提取数据!但它不会...

【问题讨论】:

  • 顺便说一句:当你有this.$el 时,为什么还要$this = ...。我建议通读backbone.js 文档。
  • 并明确 nikoshr 的答案:collection.fetch 是 asynchronous 并且您可能在 fetch 返回之前在 initialize 方法中呈现您的视图,因此集合是空的。 console.log 是wtfsynchronous,因此它无论如何都会将集合记录为已填充。您需要做的是将渲染方法绑定到集合的重置事件,以确保在填充集合后视图也被渲染
  • 谢谢,看看,集合不是空的,因为它在我仅用于测试的 console.log 中显示了它的数据
  • console.log 显示填充集合在我链接的第二个答案中进行了解释。总结:console.log 耍花招,在记录之前克隆集合,看看你得到了什么

标签: backbone.js coffeescript


【解决方案1】:

这是因为集合中还没有任何内容。

初始化器中的@collection.fetch() 是一个异步方法。您必须等到提取完成后才能遍历集合项。

fetch() 函数采用一个可选的成功回调,该回调在提取完成时触发。

因此,您可以更新您的初始化程序代码,以等到集合被提取后再调用render。这是代码。

initialize: ->
  @collection = new Store.Collections.Product()
  @collection.fetch
    success: =>
      @render()

【讨论】:

  • 你能停止一切直到集合被填满吗?
  • @CharlieDavies 这样的等待让 MVC 失败了。另一种方法是让视图监听集合以重置以执行渲染。 this.collection.on('reset', this.render, this);因此,当您进行 fetch(触发“重置”事件)时,将自动调用 render。
【解决方案2】:

其他人提到的问题是fetch是异步的,但解决方案更简单:jQuery的deferred对象:

initialize: ->
  @collection = new Store.Collections.Product()
  @collection.deferred = @collection.fetch()

  @model.bind('change:formatted', @render, this);
  @collection.deferred.done ->
    @render()

这里发生的情况是,当您调用 @collection.deferred.done 时,您是在告诉 jQuery 等到集合加载完毕后再对其执行 render,这正是您想要的。我认为这应该可行。

deferred 上的几个很好的参考:

【讨论】:

  • 更正:我认为@Paul 使用success 回调的答案实际上做了同样的事情。
  • 感谢您的帮助,这对我来说更有意义了!真的很感激!
猜你喜欢
  • 2014-04-11
  • 2012-04-05
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多