【问题标题】:Debugging Backbone.js: rendering after collection fetch()调试 Backbone.js:集合 fetch() 后渲染
【发布时间】:2012-11-27 06:55:33
【问题描述】:

我正在尝试在收集(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 的问题数量,这个功能似乎没有得到很好的记录。

【问题讨论】:

    标签: backbone.js


    【解决方案1】:

    来自fine manual

    获取 collection.fetch([options])

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

    reset 是做什么的? reset 这样做:

    重置 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" 处理程序绑定到集合since

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

    随着集合本身的变化,集合还将生成"add""remove" 事件。


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

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

    还有set

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

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

    1. 收听"add" 并使用回调处理该事件,该回调只需将一项添加到视图中,不要丢弃所有内容并重新渲染。
    2. 收听"remvoe" 并使用仅删除新删除模型的回调处理该事件。
    3. 收听"change" 并使用替换(或更新)相应项目的回调来处理。
    4. 收听"reset" 并将其绑定到render。然后将{reset: true} 传递给集合的初始fetch 调用。

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

    【讨论】:

    • 感谢您的详尽回答,希望这对其他人有用。 PS。除了官方文档,您还有其他资源可以推荐吗?
    • @Fdr:我阅读了文档和源代码以供参考。 15 年多之后,所有框架看起来都差不多。
    • 我想是的。主干中的这些事件有点跳闸:为集合引发了“重置”,但在执行 model.fetch() 时没有相似之处(这会导致发出“更改”)。 api设计薄弱?
    • 但是您如何区分对集合的更改和对其中一个模型的更改?因此添加,删除。并重置事件。您的视图/模板应该能够处理空模型,因此更改事件就足够了,如果需要,您可以通过覆盖 fetch 来修补获取的事件。
    • 我的意思是,当名称相同时,人们期望相同的行为。如果行为不同,名称也应该不同:如果是 model.fecth(),更好的命名是 model.load() 或 model.update()
    【解决方案2】:

    这在 1.0 中发生了变化

    http://backbonejs.org/#changelog

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-07
        • 2016-06-09
        • 2016-05-19
        • 2013-07-10
        相关资源
        最近更新 更多