2

特定のコレクションのモデルへの変更が発生したときにアクションを実装しようとしていますが、コレクションの、、、またはイベントにリスナーを配置しようとするとchangeaddイベントremoveは発生しません。モデルのinitialize関数に変更イベントをアタッチすると(テストのためだけに)、changeイベントは正常に発生しました。以下のビュー自体はコードを変更しませんが、コレクションに変更が加えられるたびにコードを再レンダリングする必要があります。設定に問題がある可能性がありますが、アドバイスをお願いします。以下は私のコードです:

contact.js(モデル):

define([
  'jquery',
  'underscore',
  'backbone'
], function($, _, Backbone){

  var ContactModel = Backbone.Model.extend({
        urlRoot: '/contacts'
    });

  return ContactModel;
});

contacts.js(コレクション):

define([
  'jquery',
  'underscore',
  'backbone',
  'models/contact'
], function($, _, Backbone, Contact){

  var ContactCollection = Backbone.Collection.extend({
    url: '/contacts',
    model: Contact
  });

  return ContactCollection;

});

contactlist.js(表示):

define([
  'jquery',
  'underscore',
  'backbone',
  'text!templates/contactlist.html',
  'collections/contacts'
], function($, _, Backbone, contactListTemplate, Contacts){

  var ContactListView = Backbone.View.extend({
    el: '.contact-list',
    render: function(options) {
        var that = this;
        var contacts = new Contacts();
        contacts.on("add", function() {
            console.log('change');
        });
        contacts.fetch({
            success: function(contacts) {
                var results = contacts.models;
                if (options.query || options.query === '') {
                    var results = [];
                    var query = options.query.toUpperCase();
                    for (var contact in contacts.models) {
                        if (contacts.models[contact].get('firstname').toUpperCase().indexOf(query) !== -1 ||
                                contacts.models[contact].get('lastname').toUpperCase().indexOf(query) !== -1 ||
                                contacts.models[contact].get('email').toUpperCase().indexOf(query) !== -1 ||
                                contacts.models[contact].get('phonenumber').toString().toUpperCase().indexOf(query) !== -1)
                        {
                            results.push(contacts.models[contact]);
                        }
                    }
                    options.idclicked = null;
                }
                if (!options.idclicked && results[0]) {
                    options.idclicked = results[0].get('id');
                    Backbone.history.navigate('/contacts/' + results[0].get('id'), {trigger: true});
                }
                var template = _.template(contactListTemplate, {contacts: results, idclicked: options.idclicked});
                that.$el.html(template);
                $(document).ready(function() {
                    $('.contact-list').scrollTop(options.scrolled);
                });
            }
        });
    },
    events: {
        'click .contact': 'clickContact'
    },
    clickContact: function (ev) {
        $('.contact-clicked').removeClass('contact-clicked').addClass('contact');
        $(ev.currentTarget).addClass('contact-clicked').removeClass('contact');
        window.location.replace($(ev.currentTarget).children('a').attr('href'));
    }
  });

  return ContactListView;

});
4

2 に答える 2

9

Backbone 1.0(変更ログ)以降、この質問への回答は100%正確ではなくなりました。

Backbone 1.0以降では、イベントを発生させる場合{ reset: true }はメソッドに渡す必要があります。下記参照。.fetch()reset

コレクションを呼び出すfetchと、3つの異なるイベントがトリガーされます。


collection.fetch(); //triggers the following events
  1. request:ajaxリクエストが行われる前にトリガーされます
  2. add:(複数回)データ内の各アイテムがコレクションに追加されると、このイベントが複数回トリガーされます。
  3. sync:コレクションのデータがデータプロバイダーと同期された後にトリガーされます(データがコレクションに追加され、ajaxリクエストが完了しました)

古いスタイルのバックボーンイベントに戻すには、

collection.fetch({ reset: true }); //triggers the following events
  1. request:ajaxリクエストが行われる前にトリガーされます
  2. reset:すべてのデータがコレクションに配置されたときにトリガーされます。
  3. sync:コレクションのデータがデータプロバイダーと同期された後にトリガーされます(データがコレクションに追加され、ajaxリクエストが完了しました)

コレクションがトリガーしているイベントをすばやく確認する最良の方法は、イベントにバインドしてall引数をログに記録することです。

collection.on('all', function() {
    console.log(arguments);
});
于 2013-04-07T21:56:13.350 に答える
2

を実行すると、コレクションはイベントではなくイベントfetch()をトリガーします。resetadd

contacts.on("reset", function() {
    console.log('reset');
});

これは、フェッチが完了するとすぐに、successコールバックの前に実行されます。

changeモデル自体の属性が変更されたときに実行されます。これは、投稿したコードのどこでも実行しません。

.modelsまた、一般的に私は直接アクセスしません。私はこれをします:

var results = contacts.toArray();
if (options.query || options.query === ''){
  results = contacts.filter(function(contact){
    return _.any(['firstname', 'lastname', 'email', 'phonenumber'], function(attr){
      return contact.get(attr).toString().toUpperCase().indexOf(query) !== -1;
    });
  }); 
// ...

アップデート

現在のように、レンダリング時にコレクションを作成します。理想的には、すべてのデータを再度フェッチせずに再度レンダリングできるようにする必要があるため、これはお勧めできません。

コレクション作成ロジックを次のようにビューのinitialize関数に移動します。

initialize: function(options){
  this.collection = new Contacts();
  this.collection.on('reset add remove', this.render, this);
}

これにより、コレクションが変更されると、レンダリングが自動的にトリガーされます。これはあなたにとって複雑なoptionsので、これらの引数を渡す方法を変更しようと思います。レンダリング中に使用するオプションを保存する「setOptions」関数を追加するかもしれません。理想的renderには、呼び出し前と同じようにページを再レンダリングします。通常、引数はありません。

于 2012-12-30T20:58:06.517 に答える