【问题标题】:Backbone.js Collection Not Adding ObjectsBackbone.js 集合不添加对象
【发布时间】:2012-03-12 21:59:30
【问题描述】:

我正在尝试使用 Backbone.js 从服务器获取集合数据并将其加载到我的集合对象中。我想在开始时获取这些数据,并用这些数据加载我的 html 页面。但是,我从服务器下载的数据没有正确填充到集合中。集合长度为零,有谁知道我做错了什么?

(function ($) {
    window.Menu = Backbone.Model.extend({});

    window.MenuCollection = Backbone.Collection.extend({
        model: window.Menu,
        initialize: function() {
            _.bindAll(this, 'parse');
        },
        url: function(){
            return 'http://localhost:8080/testing/123';
        },
        parse : function(resp) {
            console.log(resp);
            // this prints:
            // "[{"name":"helloworld1"},{"name":"helloworld2"}]"

            this.add(resp);
            this.add(new Menu({name:"black perl"}));
            console.log(this);
            // the length of the object in the console log is 0
        }
    });

    window.MenuView = Backbone.View.extend({
        tagName: 'li',
        initialize: function() {
            _.bindAll(this, 'render');
        },
        render: function() {
            $(this.el).html('<span>'+this.model.get('name')+'</span>');
            return this;
        }
    });

    window.MenuListView = Backbone.View.extend({
        tagName: 'ul',
        initialize: function() {
            _.bindAll(this, 'render');
        },
        render: function() {
            this.model.each(function(menu) {
                $(this.el).append(new MenuView({model:menu}).render().el);
            });

            return this;
        }
    });

    var view;
    AppView = Backbone.View.extend({
        el: $("body"),
        initialize: function () {
            this.menus = new MenuCollection();
            this.menuListView = new MenuListView({model:this.menus});
            view = this.menuListView;
            this.menus.fetch({success: function(){console.log("success");
            console.log(view.render().el);}});
        },
        events: {

        }
    });

    var appview = new AppView;

})(jQuery);

【问题讨论】:

  • 我没有看到在尝试简化示例代码方面付出了太多努力。如果您能向我们展示一个重现相同问题的非常小的代码版本,将会很有帮助。

标签: javascript backbone.js underscore.js


【解决方案1】:

您误解了parse 的工作原理:

解析 collection.parse(response)

parse 每当服务器返回集合的模型时,Backbone 都会调用 fetch。该函数传递了原始的response 对象,并应返回要添加到集合中的模型属性数组。

因此,如果您从服务器获取[{"name":"helloworld1"},{"name":"helloworld2"}],您甚至不需要parse 实现。

您在add 中看到的奇怪行为更有趣。如果我们查看fetch,我们会看到:

fetch: function(options) {
  //...
  options.success = function(resp, status, xhr) {
    collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
    if (success) success(collection, resp);
  };
  //...
}

您在没有设置add 选项的情况下调用fetch,所以事情会这样发生:

  1. collection.parse 被调用。
  2. 您的parse 添加了一些内容并调用console.log
  3. 您的解析根本不返回任何内容。
  4. 调用 collection.reset 以添加 parse 返回的内容。
  5. reset 将清除集合,然后不添加任何内容,因为 parse 没有返回任何内容。

一些console.log 实现在控制台中放置了一个实时引用,这就是为什么您在控制台中得到一个空集合的原因:console.log(this) 最终显示this reset 调用之后。

【讨论】:

  • 自从写下这个答案后,代码似乎发生了变化:github.com/jashkenas/backbone/blob/master/backbone.js#L873我们现在应该做什么?
  • @qwertynl 关于add 的部分只是对他们从parse 看到的看似奇怪的行为的解释。答案的核心是根本不需要 parse 实现。
【解决方案2】:

实际上,您遇到的另一个问题是您没有将“this”传递到视图渲染内的 for 循环的上下文中。因此,当您返回“el”元素时,您的 html 页面将是空白的,没有来自服务器的内容。

【讨论】:

  • 并且MenuListView 应该使用collection 而不是model
【解决方案3】:

请记住,从backbone.js 0.9+ 可用的解析方法 0.5.3 版不会调用 parse。

【讨论】:

    猜你喜欢
    • 2014-12-09
    • 2012-01-19
    • 2012-02-27
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    相关资源
    最近更新 更多