Backbone模型属性在被调用时引发TypeError

时间:2012-04-30 18:54:59

标签: javascript backbone.js coffeescript

我正在尝试访问模型中的数组项并且它会引发错误,但似乎找到了正确的属性并将其写入控制台仍然

class GD.Views.Place extends Backbone.View
  template: JST['mobile/templates/place']
  initialize: ->
    @model.on('change', @render, this)
  render: ->
    $(@el).html(@template(place:@model, open:@openNow() ))
    console.log @model.get("coordinates")
    console.log @model.get("coordinates")[0]
    console.log @model.get("coordinates")[1]
    console.log("done")
    this
  openNow: ->
    ...

视图未在屏幕上呈现,我在控制台中看到此消息

Uncaught TypeError: Cannot read property '0' of undefined
  GD.Views.Place.Place.render
  GD.Routers.Main.Main.place
  _.extend.route
  (anonymous function)
  _.some._.any
  _.extend.loadUrl
  _.extend.start
  window.GD.init
  (anonymous function)
  jQuery.Callbacks.fire
  jQuery.Callbacks.self.fireWith
  jQuery.extend.ready
  DOMContentLoaded
[51.4528837, -0.9739059999999428]
51.4528837
-0.9739059999999428
done

错误消息指的是上面的第2和第3个console.log行。当访问嵌入式哈希中的其他属性时,它似乎也会引发错误。

我不明白为什么会发生这种情况或如何解决这个问题。感谢您的帮助/耐心!

1 个答案:

答案 0 :(得分:4)

Backbone视图的常用模式是:

v = new V
$(something).append(v.render().el)

如果将其与用于初始化模型的常用模式相结合:

m = new M
m.fetch() # asynchronous!

那么你可以得到这个:

m = new M
m.fetch()
v = new V(model: m)
$(something).append(v.render().el)

这将允许v.render()调用内的append在从服务器获取模型之前发生。在您的情况下,这意味着上面的@model.get('coordinates')调用中undefined将为v.render(),您会得到:

Uncaught TypeError: Cannot read property '0' of undefined
...

然后,m.fetch()从服务器和triggers a "change" event获取其数据,然后该事件将在您的视图上调用render,您将获得此信息:

[51.4528837, -0.9739059999999428]
51.4528837
-0.9739059999999428
done

这些消息正是您在控制台中看到的。

我猜你做的是这样的事情(如上所述):

m = new M
m.fetch()
v = new V(model: m)
$(something).append(v.render().el)

尝试检查@model内是否实际加载render,如果不是,则抛出某种“loading ...”消息;然后让"change"事件触发“真实”渲染。


PS:您可以在CoffeeScript中使用@代替this

initialize: ->
  @model.on('change', @render, @)
render: ->
  #...
  @

您还可以使用fat arrow (=>)来定义render方法,而不必担心向@model.on提供上下文:

initialize: ->
  @model.on('change', @render)
render: =>
  #...
  @

此外,如果您使用的是最新版本的Backbone,则视图实例中会有$el,因此您可以:

render: =>
  @$el.html(...)
  #...
  @