Backbone.js中的集合不会触发事件

时间:2012-12-30 20:50:48

标签: javascript backbone.js backbone-events

当我尝试在changeadd或{{1}上放置一个侦听器时,我试图在触发给定集合中的模型更改时实现操作我的集合上的事件,没有事件被触发。当我将更改事件附加到模型的remove函数(仅用于测试)时,initialize事件已成功触发。下面的视图本身不会更改代码,但我希望每当对集合进行更改时它都会重新呈现。我的设置可能有问题,但我想得到你的建议。以下是我的代码:

contact.js(型号):

change

contacts.js(收藏):

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

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

  return ContactModel;
});

contactlist.js(查看):

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

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

  return ContactCollection;

});

2 个答案:

答案 0 :(得分:9)

自Backbone 1.0(change log)以来,这个问题的答案不再是100%准确。

在Backbone 1.0+中,如果您希望触发{ reset: true }事件,则必须将.fetch()传递到reset方法。见下文。

在集合上调用fetch现在会触发3个不同的事件:


collection.fetch(); //triggers the following events
  1. request:在发出ajax请求之前触发
  2. add :(多次)此事件将在每个项目中被触发多次 数据将添加到集合中。
  3. sync:在集合上的数据与之同步后触发 数据提供者(数据添加到集合,ajax请求已完成)

  4. 要恢复旧式骨干事件,您需要调用

    collection.fetch({ reset: true }); //triggers the following events
    
    1. request:在发出ajax请求之前触发
    2. reset:将所有数据放入集合时触发。
    3. sync:在集合上的数据与之同步后触发 数据提供者(数据添加到集合,ajax请求已完成)

    4. 快速查看集合触发的事件的最佳方法是绑定到all事件并记录参数:

      collection.on('all', function() {
          console.log(arguments);
      });
      

答案 1 :(得分:2)

运行fetch()时,该集合会触发reset事件,而非add

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将重新呈现页面与调用之前的页面完全相同,它通常不具有参数。