2

私は Backbone を初めて使用し、Backbone を接続した JSON API を使用して Rails アプリを開発しました。

サイトを直接使用してリンクをたどると、すべてがうまく機能します.

/#/1 へのリンクをクリックすると、投稿が 1 の ID をたどる番組ページに移動します。

ただし、ページを更新すると、その情報が表示されなくなり、エラーがスローされます。

"Uncaught TypeError: 未定義のメソッド 'toJSON' を呼び出せません"

コンソールにアクセスしてビューBackboneBlog.router.show(1)にアクセスすると、正しく機能します。問題が発生するのは私が行ったときだけhttp://localhost:3000/#/1です。ただし、インデックス ページのリンクをクリックすると、直接リンクします。 http://localhost:3000/#/1

さらに陽気なことBackboneBlog.router.postsは正しいです。ただし、私のコードでそれを正確に入力すると、 add BackboneBlog.router.posts.get(1)、 undefined が返されます。ただし、同じ 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

backbone_blog.js.coffee --

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

皆さんありがとう!<3

編集:
tl;dr: 直接アクセスするhttp://localhost:3000/#/1とエラーが発生しますが、そこにリンクすると問題なく動作します。コンソールに入力すると、正常に動作します。機能しないのは、URL に直接移動した場合のみです。それでも、 show メソッドでは、投稿を直接取得するまですべてが機能します

4

1 に答える 1

1

あなたの問題は、まだフェッチされていないモデルを渡していることです。したがって、モデルは未定義であるため、未定義のモデルで .toJSON を呼び出すことはできません。非同期関数は、特に console.log に何が起こっているかを記録しようとするときに、誤解を招く可能性があります。この例では、未定義のモデルを console.log に記録します。そのモデルがフェッチされると、ログに記録した未定義のモデルは、フェッチされたデータに置き換えられます。したがって、順番に発生しているように見えますが、実際には未定義のモデルをビューに渡しています。

そのため、ショー ビューをナビゲートすると、すべてが正しく機能します。これは、コレクションが既に取得されているためです。ショー ビューから更新する場合、コレクションを取得する必要がありますが、ショー ビューはコレクションが取得されるのを待機していません。

これが理にかなっていることを願っています。しかし、私が何を意味するかを示すために、フェッチされているコレクションの成功コールバックでのみ、ルーターで show メソッドを呼び出します。

さらにお手伝いできることがあればお知らせください。

于 2012-10-22T06:54:19.943 に答える