Backbone:向集合添加新模型不起作用

时间:2014-08-04 18:21:07

标签: javascript backbone.js

我在骨干网中创建了一个众所周知的待办事项列表应用,但有一个功能无效,mycollection.add()方法。

使用todoItems.remove(todoItem.at(0))删除项目时,一切正常。 我遇到的问题是添加新项目时:

var newItem = new todoItem({ description: "cereal killer", status: "complete" });

todoItems.add(newItem) - >这不会将它添加到集合中,长度仍然相同。

我可以添加新项目的唯一方法是先删除一项,然后添加项目,但只能使用一项。

有任何线索吗?

这是主要代码:

app.js

var TodoItem = Backbone.Model.extend({
    defaults: {
        description: "Pick up milk", 
        status: "incomplete", 
        id: 1
    },
    toggleStatus: function(){
        if(this.get('status') === 'incomplete'){
          this.set({'status': 'complete'});
        } else {
          this.set({'status': 'incomplete'});
        }
        this.save();
    } 
});

var TodoItems = Backbone.Collection.extend({
    model: TodoItem,
    localStorage: new Backbone.LocalStorage("choose-some-identifier"),

    initialize: function () {
        this.on('remove', this.hideModel, this);
    },

    hideModel: function (model) {
        model.trigger('hide');
    }
});

var TodosView = Backbone.View.extend({
    initialize: function () {
        this.collection.on('add', this.addOne, this);
        this.collection.on('reset', this.addAll, this);
    },
    render: function() {
        this.addAll();
        // this.collection.forEach(this.addOne, this);
        return this;
    },

    addOne: function (todoItem) {
        var todoView = new TodoView({ model: todoItem });
        this.$el.append(todoView.render().$el);
    },

    addAll: function () {
        this.collection.forEach(this.addOne, this);     
    }

});

var TodoView = Backbone.View.extend({
    tagName: 'article',
    id: 'todo-view',
    className: 'todo',

    template: _.template('<h3 class="<%= status %>">' + 
        '<input type=checkbox ' + 
        '<% if (status === "complete") print("checked") %> />' + 
        '<%= description %></h3>'),

    events: {
        "change input": "toggleStatus"
    },

    toggleStatus: function () {
        this.model.toggleStatus();
    },

    remove: function(){
        this.$el.remove();
    },

    initialize: function(){
        this.render();
        this.model.on('change', this.render, this);
        this.model.on('destroy', this.remove, this);
        this.model.on('hide', this.remove, this);
    },

    render: function () {
        var attributes = this.model.toJSON();
        this.$el.html(this.template(attributes));
        return this;
    }
});

var todoItems = new TodoItems([
    {
        description: 'Jeffrey Way',
        status: "incomplete"
    },
    {
        description: 'John Doe',
        status: "incomplete"
    },
    {
        description: 'Sally Doe',
        status: "incomplete"
    }
]);

var todosView = new TodosView({ collection: todoItems});
$(document.body).append(todosView.render().el);

1 个答案:

答案 0 :(得分:2)

问题在于:

defaults: {
    description: "Pick up milk", 
    status: "incomplete", 
    id: 1
}

您已将id设为默认值。一个id应该是唯一的,你试图添加另一个模型而不指定一个新的id,所以Backone有用地注意到你已经有一个带有该id的模型,所以它不会添加它。

解决方案:您不应该设置默认ID,在本地创建模型时,正常流程是: - 创建没有id的模型 - 在某些时候.save它 - 服务器响应所有属性+保存后的ID

当然,获取已存在于服务器上的模型应该已经有了id。

PS你不需要为单个集合(或获取)制作哈希:

this.set('status', 'complete');

PPS在您看来,最好使用listenTo

this.listenTo(this.collection, 'add', ...);

这可以防止在某些情况下出现memleaks,并且可以更轻松地批量停止收听事件。