【问题标题】:Backbone reset event bound to collection not firing when collection is loaded with data当集合加载数据时,绑定到集合的主干重置事件未触发
【发布时间】:2026-01-18 09:15:01
【问题描述】:

我是 Backbone 的新手,从 Todos 示例开始。之后,我为 Contacts 而不是 Todos 创建了该示例的新版本,它使用 Ruby on Rails Web 应用程序,并且它使用关联的 REST API 而不是 localstorage 来实现持久性。进行修改后,我能够成功地让 Backbone 应用程序更新 Rails 应用程序,但我无法让 Backbone 视图呈现 Backbone 应用程序从 Rails REST API 接收的数据。我已经在调试器中单步执行了代码,可以看到:

  1. 调用函数以填充视图的事件被绑定到模型集合
  2. 当我获取模型数据时,集合会使用来自服务器的数据进行更新
  3. 但是,绑定到集合的重置事件不会触发

谁能指出可能导致重置事件不触发的原因?我的代码如下:

收藏

var ContactsList = Backbone.Collection.extend({
  model: Contact,
  url: 'http://localhost:3000/contacts.json',
});

var Contacts = new ContactsList;

AppView:

var AppView = Backbone.View.extend({

  el: $("#contactapp"),
  events: {
    "keypress #new-contact":  "createOnEnter"
  },

  initialize: function() {

    this.input = this.$("#new-contact");

    Contacts.bind('add', this.addOne, this);
    Contacts.bind('reset', this.addAll, this);
    Contacts.bind('all', this.render, this);

    Contacts.fetch();
  },

  addOne: function(contact) {
    var view = new ContactView({model: contact});
    this.$("#contact-list").append(view.render().el);
  },

  addAll: function() {
    Contacts.each(this.addOne);
  },

  createOnEnter: function(e) {
    if (e.keyCode != 13) return;
    if (!this.input.val()) return;

    Contacts.create({first_name: this.input.val()});
    this.input.val('');
  },

});

var App = new AppView;

【问题讨论】:

  • 所以addAll 不会在重置发生时被调用?你在那儿放了一个断点让它飞起来?
  • 没错。我在整个过程中都放置了断点,可以看到绑定到集合的事件以及获取数据的获取。从那里它只是继续前进,而不是调用 addAll 。有什么想法吗?
  • 很难说,根据你的代码。我会在backbone.js的第746行和第759行设置一个断点,看看是否触发了事件以及你的函数是否在那个时间点绑定到事件。
  • 在我的backbone.js第746行是:'this.iframe.document.open().close();'这是你指的那条线吗?
  • 尝试调用Contacts.reset(),看看是否触发了事件。

标签: ruby-on-rails backbone.js backbone.js-collections


【解决方案1】:

您可能会在视图中得到一个由el: $("#contactsapp") 配置返回的空 jQuery 选择器。

http://lostechies.com/derickbailey/2011/11/09/backbone-js-object-literals-views-events-jquery-and-el/

不要使用 jQuery 选择器作为对象字面量值。使用 Backbone 的视图,您只需提供选择器字符串:

el: "#contactsapp"

但这无论如何都是个坏主意。您应该让视图呈现它自己的 el,并使用其他代码用视图填充“#contactsapp”元素:

$(function(){
  view = new AppView();
  view.render();
  $("#contacts").html(view.el);
});

查看以上链接了解更多信息。

【讨论】:

  • 我更正了这个问题,但仍然有同样的问题。在 Contacts.fetch() 之后,重置事件不会触发。
【解决方案2】:

经过多次调试,我发现绑定的reset 事件没有被触发,因为我使用的是旧版本的主干.js。在我使用的版本中,refresh 事件被触发而不是reset 事件。一旦我升级到新版本的主干.js,reset 事件就会触发

【讨论】: