2

所以我是 Backbone 的新手,我开发了一个带有 JSON API 的 Rails 应用程序,我已经将 Backbone 连接到了。

当我直接使用该网站并点击链接时,一切都很好。

就像我单击指向 /#/1 的链接一样,它会将我指向显示页面,其中帖子遵循一个 ID。

但是,如果我刷新页面,它将不再显示该信息,并引发错误:

“未捕获的类型错误:无法调用未定义的方法‘toJSON’”

当我转到控制台并访问我的视图BackboneBlog.router.show(1)时,它确实可以正常工作。只有当我去的时候http://localhost:3000/#/1,我才会遇到问题。但是,当我单击索引页面中的链接时,该链接直接链接到 http://localhost:3000/#/1

更搞笑的BackboneBlog.router.posts是正确的。但是,如果在我的代码中我准确地输入了那个,但是 add BackboneBlog.router.posts.get(1),它返回未定义。但是,如果我在控制台中使用相同的 URL 运行该确切代码,它就可以工作。

这是我的代码:

posts_router.js.coffee--

class BackboneBlog.Routers.PostsRouter extends Backbone.Router
  initialize: ->
    @posts = new BackboneBlog.Collections.PostsCollection()
    @posts.fetch()

  routes:
    "": "index"
    "new"      : "newPost"
    "index"    : "index"
    ":id/edit" : "edit"
    ":id"      : "show"
    ".*"       : "index"

  newPost: ->
    @view = new BackboneBlog.Views.Posts.NewView(collection: @posts)
    $("#posts").html(@view.render().el)

  index: ->
    @view = new BackboneBlog.Views.Posts.IndexView(posts: @posts)
    $("#posts").html("")
    $("#posts").html(@view.render().el)

  show: (id) ->
    console.log(@posts) #puts PostsCollection, with posts in it
    console.log(id) #puts 1
    @post = @posts.get(id)
    console.log(@post) #puts undefined 
    @view = new BackboneBlog.Views.Posts.ShowView(model: @post)
    $("#posts").html(@view.render().el)

  edit: (id) ->
    post = @posts.get(id)

    @view = new BackboneBlog.Views.Posts.EditView(model: post)
    $("#posts").html(@view.render().el)

show_view.js.coffee --

BackboneBlog.Views.Posts ||= {}

class BackboneBlog.Views.Posts.ShowView extends Backbone.View
  template: JST["backbone/templates/posts/show"]

  render: ->
    $(@el).html(@template(@model.toJSON() ))
    return this

index_view.coffee --

BackboneBlog.Views.Posts ||= {}

class BackboneBlog.Views.Posts.IndexView extends Backbone.View
  template: JST["backbone/templates/posts/index"]

  initialize: () ->
    @options.posts.bind('reset', @addAll)

  addAll: () =>
    $("tbody").html("")
    @options.posts.each(@addOne)

  addOne: (post) =>
    view = new BackboneBlog.Views.Posts.PostView({model : post})
    @$("table").append(view.render().el)

  render: =>
    $(@el).html(@template(posts: @options.posts.toJSON() ))
    @addAll()

    return this

骨干博客.js.coffee --

window.BackboneBlog =
  Models: {}
  Collections: {}
  Routers: {}
  Views: {}
  init: ->
    @router = new BackboneBlog.Routers.PostsRouter()
    Backbone.history.start()

谢谢大家!<3

编辑:
tl;博士:如果我直接访问http://localhost:3000/#/1我会得到错误,但是,如果我链接到那里,它工作得很好。如果我在控制台中键入它,它工作正常。只有当我直接导航到 URL 时它才不起作用。即便如此,在 show 方法中,一切正常,直到我直接得到帖子

4

1 回答 1

1

您的问题是您正在传递一个尚未获取的模型。因此模型是未定义的,因此您不能在未定义的模型上调用 .toJSON。异步函数非常具有误导性,尤其是在尝试 console.log 发生的事情时。所以拿这个例子来说,你 console.log 一个未定义的模型。现在,当获取该模型时,您记录的未定义模型将被替换为已获取的数据。因此,它看起来好像是按顺序发生的,但实际上您将未定义的模型传递到您的视图中。

这就是为什么当您浏览您的显示视图时,一切正常。这是因为您的收藏已被提取。当您从显示视图刷新时,仍需要获取集合,但您的显示视图不会等待您的集合被获取。

我希望这是有道理的。但是为了向您展示我的意思,请仅在获取集合的成功回调时调用路由器上的 show 方法。

让我知道我是否可以进一步帮助您。

于 2012-10-22T06:54:19.943 回答