9

我正在尝试在集合(Backbone 0.9.2)上的 fetch() 之后执行基本的渲染():

var ProjectListView = Backbone.View.extend({
        el: $('#container'),
        initialize: function () {
            this.collection = new ProjectsCollection();
            this.collection.bind("change", _.bind(this.render, this));
            this.collection.fetch({ success: function () { console.log("collection fetched"); } });
            ...
             }, 
        render: function () {
            console.log("rendered");
            ...

创建新的视图实例打印出来:

    collection fetched 

所以 render() 永远不会在 fetch() 之后被调用。我在这里做错了什么?目前没有例外。

任何提示如何在主干中调试这些东西?

附言。考虑到关于 SO 的问题数量,这个特性似乎没有得到很好的记录。

4

3 回答 3

29

来自精美手册

拿来 collection.fetch([options])

从服务器获取此集合的默认模型集,当它们到达时重置集合。[...] 当模型数据从服务器返回时,集合将重置。

有什么作用resetreset做这个:

重启 collection.reset(models, [options])

[...] 使用reset将集合替换为新的模型列表(或属性哈希),"reset"最后触发单个事件。

因此fetch调用reset更新集合的模型并reset触发"reset"事件,而不是"change"事件。模型都没有改变,集合的"change"事件来自它的模型。

您应该render必须"reset"

initialize: function () {
    this.collection = new ProjectsCollection();
    this.collection.bind("reset", _.bind(this.render, this));
    this.collection.fetch(...);
}

如果要侦听"change"包含模型上的事件,则可以将"change"处理程序绑定到集合,因为

您可以绑定"change"事件以在修改集合中的任何模型时收到通知,
[...]
为方便起见,在集合中的模型上触发的任何事件也将直接在集合上触发。

随着集合本身的变化,集合也会生成"add"和事件。"remove"


较新版本的 Backbone 在以下期间不再重置集合fetch

当模型数据从服务器返回时,它使用set来(智能地)合并获取的模型,除非您通过{reset: true},在这种情况下,集合将(有效地)重置

并且set

[...] 使用传递的模型列表对集合执行“智能”更新。如果列表中的模型尚未在集合中,它将被添加;如果模型已经在集合中,它的属性将被合并;如果集合包含列表中不存在的任何模型,它们将被删除。发生这种情况时会触发所有适当"add""remove", 和"change"事件

因此,对于较新版本的 Backbone,您需要列出"add""remove""change"事件(基于集合的视图无论如何都应该监听);您也可以{reset: true}在初始时使用fetch并聆听"reset"。对于基于集合的视图,我建议采用以下方法:

  1. 使用一个简单地将一个项目添加到视图中的回调来监听"add"和处理该事件,不要扔掉所有东西并重新渲染。
  2. 使用仅删除新删除模型的回调来侦听"remvoe"并处理该事件。
  3. 使用替换(或更新)适当项目的回调来监听"change"并处理它。
  4. 收听"reset"并将其绑定到render. 然后传递{reset: true}给集合的初始fetch调用。

这将捕获重要事件,并且集合视图将做最少的工作来处理每个事件。当然,这种策略并不适用于所有情况,但我认为这是一个很好的起点。

于 2012-11-27T08:01:04.090 回答
8

这在 1.0 中发生了变化

http://backbonejs.org/#changelog

“如果您想继续使用“重置”,请传递 {reset: true}。”

于 2013-05-31T15:44:37.627 回答
3

好的,所以在有人可以解释为什么绑定不起作用之前,我使用了以下解决方法:

   initialize: function () {
            var self = this;
            this.collection = new ProjectsCollection();
            this.collection.fetch({ success: function () { self.render(); } });

于 2012-11-27T07:35:56.890 回答