1

シナリオ

私はバックボーンアプリに取り組んでいます。現在起こっていることは、ユーザーがページの編集リンクをクリックすると、フォームが表示されるはずです。イベントではなくバックボーンルーターを使用してこれを実装しようとしています。イベントオブジェクトを使用すると、完全に正常に機能します。ルーターを使用するために、グローバル イベントを使用しています。

問題

問題は、ユーザーが編集リンクをクリックすると、コンソールに次のエラーが表示されることです

Uncaught TypeError: Object 10 has no method 'toJSON'             views.js:57

このエラーは、views.js の 57 行目で、this.model.toJSON()ルーター経由でモデルを渡していないのに使用しているためです。ルーターを介してモデルを渡す方法がわかりません

これが私のルーターです。注: 次のコードはすべて別のファイルにあります。

App.Router = Backbone.Router.extend({
    routes: {
        'contacts/:id/edit': 'editContact'
    },

    editContact: function (id) {
        console.log('yahhhhh');
        vent.trigger('contact:edit', id);
    }
});

上記のルーターでは、関数内でイベントをトリガーしていeditContactます。次に、次の関数で上記のイベントをリッスンしていinitializeます。

App.Views.App = Backbone.View.extend({
    initialize: function () {
        vent.on('contact:edit', this.editContact, this);
    },

    editContact: function (contact) {
        var editContactView = new App.Views.EditContact({ model: contact });
        $('#editContact').html(editContactView.render().el);
    }
});

関数で聞いた後eventinitialize関数を呼び出しており、キーワードを使用してeditContact渡しています。関数内で、次のビューのインスタンスを作成し、表示する必要があるフォームをレンダリングしています。modelthiseditContactEditContact

App.Views.EditContact = Backbone.View.extend({
    template: template('editContactTemplate'),

    render: function () {
        var html = this.template(this.model.toJSON());  //<--- this is line 57
        this.$el.html(html);
        return this;
    }
});

上記のすべてを実行した後、フォームが表示されず、上記のエラーが発生します。

質問

モデルをルーター経由で EditContact 内のレンダリング関数に渡して、機能を開始するにはどうすればよいですか?

アップデート

これが私のモデルです

App.Models.Contact = Backbone.Model.extend({
    urlRoot : '/contacts'
});
4

1 に答える 1

1

あなたのeditContactメソッドでは、引数はルーターから先に渡すことをcontact指します。idビューのモデルを使用して新しいビューを初期化するnew App.Views.EditContact({ model: contact })と、予想どおり id になります。

ID をモデル インスタンスにマップする必要があります。IMHOこれを行う正しい場所はルーターです:

editContact: function (id) {
    var contact = new App.Models.Contact({id:id});
    vent.trigger('contact:edit', contact);
}

この時点で、モデルにはidプロパティ セットしかないことに注意してください。編集のためにモデルのプロパティを入力する必要がある場合はfetch、サーバーからモデルを取得してから、イベントをトリガーする必要があります。

editContact: function (id) {
    var contact = new App.Models.Contact({id:id});
    contact.fetch().done(function() {
      vent.trigger('contact:edit', contact);
    });
}

コメントに基づいて編集:一般的に言え、ルーターには何も渡すべきではありません。ルーターは、すべての新しいリクエスト (url の変更) の開始点である必要があります。ページの変更間で何らかの状態を保持したい場合は、データをルーターレベルに保存し、モデルとコレクションをビューから「下に」渡す必要があります。

単純化したシナリオでは、これはルーター内のコレクションへの参照を初期化して保存することを意味します。何かのようなもの:

var Router = Backbone.Router.extend({
  initialize: function() {
    this.contactCollection = new App.Collections.Contacts();
  },

  editContact: function (id) {
    id = parseInt(id, 10);
    if(_.isNaN(id)) {
      //error...
    }
    //try to get a model from the collection
    var contact = this.contactCollection.get(id);

    //if not found, create, add and fetch
    if(!contact) {
      contact = new App.Models.Contact({id:id});
      this.contactCollection.add(contact);
      contact.fetch().done(function() {
        vent.trigger('contact:edit', contact);
      });
    } else {
      vent.trigger('contact:edit', contact);
    }
  }
});

これは単なるコード例であり、必ずしも行ごとに実装する方法ではないことに注意してください。古くなった可能性のあるモデルをビューに表示してもよいのか、それとも常にサーバーからフェッチする必要があるのか​​を検討する必要があります。実際には、コレクションの状態をルーターで直接処理するのではなく、nice クラスで抽象化することもできます。

これがあなたの質問に答えることを願っています。

于 2013-02-03T11:17:54.803 に答える