Javascript Backbone.js和下划线.js将此绑定到this.collection.add

Javascript Backbone.js和下划线.js将此绑定到this.collection.add,javascript,backbone.js,underscore.js,Javascript,Backbone.js,Underscore.js,我对使用 this.collection.bind('add',appendItem) 及 appendItem是在backbone.js视图中为视图集合定义的函数。对于appendSet,问题是我想通过嵌套模型来扩展教程,但是当我添加一个项时,如果我使用上面的行,我已经将appendItem和appendSet绑定到add函数,因此add函数不知道这应该是什么 (关于bind的功能的快速提醒:) 那么,我如何继续使用 this.collection.add(thisItem) 并且仍然可

我对使用

this.collection.bind('add',appendItem) 

appendItem是在backbone.js视图中为视图集合定义的函数。对于appendSet,问题是我想通过嵌套模型来扩展教程,但是当我添加一个项时,如果我使用上面的行,我已经将appendItem和appendSet绑定到add函数,因此add函数不知道这应该是什么

(关于bind的功能的快速提醒:)

那么,我如何继续使用

this.collection.add(thisItem)
并且仍然可以避免绑定问题简言之:是否有方法调用this.collection.add(thisItem)并告诉add函数关键字“this”应该是指appendItem而不使用bind函数

如果有人要求,我可以包含我的代码,但我认为它有点长,有点笨拙,而且可能没有任何用处

编辑:

我的代码的逻辑是这样的。一个项目是一个具有多个属性的模型以及与之相关联的集合。我只是在学习一个教程,他使用这个.collection.bind('add',appendItem)来渲染这些对象,这样当你调用this.collection.add时,appendItem就会被调用。以下是appendItem的代码:

appendItem: function(item){
       alert("append exercise called in allExerciseview");
       var itemView=new ItemView({
         model: Item
       });
       $('ul',this.el).append(itemView.renderItem().el);
      }
我找不到this.collection.add的源代码,但我假设在该函数中包含此代码引用appendItem调用appendItem函数简而言之:原因是此代码:

this.collection.bind('add',appendItem) 
这样当你打电话的时候

this.collection.add(thisItem)
它也运行

thisItem.appendItem()
解除它们的绑定,只运行this.collection.add(thisItem),然后分别运行thisItem.appendItem()对我不起作用

我的示例代码:

(function($){
    Backbone.sync = function(method, model, success, error) {
        success();
    };

    var Set = Backbone.Model.extend({
        defaults: {
            SetName:"Set "
            //more properties...
        },
        initialize: function(){
            alert("you've created a new set");
            this.bind("error",function(model,error){
                alert(error);
            });
        }
    });

    var SetCollection = Backbone.Collection.extend({
        model:Set
    });

    var SetView = Backbone.View.extend({
        events: {
            'click button.deleteSet': 'removeSet'
        },
        initialize: function(){
            alert('initialize called in setview');
            _.bindAll(this,'renderSet', 'unrenderSet', 'removeSet');
        /*this.model.bind('change',this.renderSet);
         this.model.bind('remove',this.unrender); Not sure if I should do this*/
            return this; //apparently for chainable calls    
        },
        renderSet: function(){
            alert('renderset called in setview');
            $(this.el).html('a set template'); //add button after so you can test delete
            return this;
        },
        unrenderSet: function(){
            alert('unrenderset called in setview');
            $(this.el).remove();
        },
        removeSet: function(){
            alert('removeset called in setview');
            this.model.destroy();
        }
    });

    var AllSetView = Backbone.View.extend({
        el: $('body'), //el attaches to existing element <-- what does this mean?
        events: {
            'click button#addSetButton': 'addSet'
        },
        initialize: function(){
            alert('initialize called in allsetview');
            _.bindAll(this,'renderAllSet', 'addSet', 'appendSet');
            this.collection = new SetCollection();
            this.collection.bind('add', this.appendSet); // Problem here...
            this.counter = 0;
            this.renderAllSet(); 
        },
        renderAllSet: function(){
            alert('renderallset called in allsetview');
            var self = this; 
            $(this.el).append('<button id="addSetButton"> Add Set </button>');
            $(this.el).append('<ul></ul>');
            _(this.collection.models).each(function(set){ //in case collection is not empty
                self.appendSet(set);
            },this); 
        },
        addSet: function(){
            alert('addSet called in allsetview');
            this.counter++;
            var thisSet = new Set();
            thisSet.set({SetName:thisSet.get('SetName')+this.counter});
            this.collection.add(thisSet); //add is a function defined for the collection
        },
        appendSet: function(item){
            alert("append set called in allsetview");
            var setView = new SetView({
                model: Set //DO NOT CAPITALIZE!!!... or do capitalize?... ack
            });
            $('ul',this.el).append(setView.renderSet().el);
        }
    });

    var allsetview = new AllSetView(); //for testing

    var Item = Backbone.Model.extend({
        defaults: {
            ItemName: 'Enter an Item'
            //more properties
        },
        initialize: function(){
            alert('youve created a new item');
            var set1 = new Set();
            var setCollection = new SetCollection([set1]);
            this.set({sets:setCollection});
            this.bind("error",function(model,error){
                alert(error);
            });
        }
    });

    var ItemCollection = Backbone.Collection.extend({
        model:Item
    });

    var ItemView = Backbone.View.extend({
        events: {
            'click button.deleteItem': 'removeItem'
        },
        initialize: function(){
            alert('initialize called in itemview');
            _.bindAll(this,'renderItem', 'unrenderItem', 'removeItem');
            //this.model.bind('change',this.renderItem);
            //this.model.bind('remove',this.unrender); Not sure if I should do this
            return this; //apparently for chainable calls    
        },
        renderItem: function(){
            alert('renderitem called in Itemview');
            $(this.el).html('an item template'); //add button after so you can test delete
            return this;
        },
        unrenderItem: function(){
            alert('unrenderitem called in itemview');
            $(this.el).remove();
        },
        removeItem: function(){
            alert('removeItem called in itemview');
            this.model.destroy();
        }
    });

    alert ("before itemview creation");
    var itemview = new ItemView();
    alert ("now after");

    var AllItemView = Backbone.View.extend({
        el: $('body'), //el attaches to existing element <-- what does this mean?
        events: {
            'click button#addItemButton': 'addItem'
        },
        initialize: function(){
            alert('initialize called in allitemview');
            _.bindAll(this,'renderAllItem', 'addItem', 'appendItem');
            this.collection = new ItemCollection();
            this.collection.bind('add', this.appendItem); //Problem here
            this.counter = 0;
            this.renderAllItem(); 
        },
        renderAllItem: function(){
            alert('renderallitem called in allitemview');
            var self = this; //why
            $(this.el).append('<button id="addItemButton"> Add Item </button>');
            $(this.el).append('<ul></ul>');
            _(this.collection.models).each(function(item){ //in case collection is not empty
                self.appendItem(item);
            },this); //what is this function
        },
        addItem: function(){
            alert('addItem called in allitemview');
            this.counter++;
            var thisItem = new Item();
            thisItem.item({ItemName:thisItem.get('ItemName')+this.counter
            });
            this.collection.add(thisItem); //add is a function defined for the collection
            this.appendItem(thisItem);
        },
        appendItem: function(item){
            alert("append item called in allItemview");
            var itemView = new ItemView({
                model: Item //DO NOT CAPITALIZE!!!... or do capitalize?... 
            });
            $('ul',this.el).append(itemView.renderItem().el);
        }
    });
})(jQuery);
(函数($){
Backbone.sync=函数(方法、模型、成功、错误){
成功();
};
var Set=Backbone.Model.extend({
默认值:{
集合名称:“集合”
//更多属性。。。
},
初始化:函数(){
警报(“您已创建了一个新集合”);
this.bind(“错误”,函数(模型,错误){
警报(错误);
});
}
});
var SetCollection=Backbone.Collection.extend({
型号:套
});
var SetView=Backbone.View.extend({
活动:{
'单击按钮。删除集':'删除集'
},
初始化:函数(){
警报(“在setview中调用初始化”);
_.bindAll(这是“renderSet”、“underset”、“removeSet”);
/*this.model.bind('change',this.renderSet);
this.model.bind('remove',this.unnder);不确定是否应该这样做*/
返回此;//对于可链接调用
},
renderSet:function(){
警报(“在setview中调用了renderset”);
$(this.el).html('a set template');//之后添加按钮,以便可以测试删除
归还这个;
},
未指定:函数(){
警报(“在setview中调用了Underset”);
$(this.el).remove();
},
removeSet:function(){
警报(“在setview中调用removeset”);
this.model.destroy();
}
});
var AllSetView=Backbone.View.extend({

el:$('body'),//el附加到现有元素我认为您的目标是呈现某种层次结构

首先: 在appendItem函数中,itemView的模型不应该是
model:item
而不是
model:item
。我看不到在任何地方定义了项

接下来,你为什么不使用

appendItem似乎是多余的。在集合更改后,您似乎还想添加一个新视图。在这种情况下,您可能希望为集合或应用程序的路由器创建一个视图,以将事件绑定到更改。此问题可能会有所帮助:


希望这会有所帮助!

为什么要将两个不同的方法绑定到同一个集合回调?在添加单个项时,与添加整个项集时,您是否尝试执行某些操作?(这与嵌套模型无关,这是一个完全独立的问题)请参见编辑。感谢您的帮助,我将添加我的代码,这样您就可以看到我到底在做什么/出错了。一秒钟。我只是在遵循一个教程,所以我所做的每件事都没有充分的理由>您完全正确,因为我正在尝试呈现层次结构。问题是,我所遵循的教程依赖于绑定添加和附加项目或附件集分别。当您有层次结构时,这会导致问题。我想知道如何以允许我具有层次结构的方式执行此操作。它是将项目添加到集合中还是不渲染它?当前它将该项添加到集合中,但add无法调用appendItem,而appendItem是呈现该项的原因。您是你完全正确,我刚刚解决了这个问题,它与选择器有关。我会尽快发布完整的答案
(function($){
    Backbone.sync = function(method, model, success, error) {
        success();
    };

    var Set = Backbone.Model.extend({
        defaults: {
            SetName:"Set "
            //more properties...
        },
        initialize: function(){
            alert("you've created a new set");
            this.bind("error",function(model,error){
                alert(error);
            });
        }
    });

    var SetCollection = Backbone.Collection.extend({
        model:Set
    });

    var SetView = Backbone.View.extend({
        events: {
            'click button.deleteSet': 'removeSet'
        },
        initialize: function(){
            alert('initialize called in setview');
            _.bindAll(this,'renderSet', 'unrenderSet', 'removeSet');
        /*this.model.bind('change',this.renderSet);
         this.model.bind('remove',this.unrender); Not sure if I should do this*/
            return this; //apparently for chainable calls    
        },
        renderSet: function(){
            alert('renderset called in setview');
            $(this.el).html('a set template'); //add button after so you can test delete
            return this;
        },
        unrenderSet: function(){
            alert('unrenderset called in setview');
            $(this.el).remove();
        },
        removeSet: function(){
            alert('removeset called in setview');
            this.model.destroy();
        }
    });

    var AllSetView = Backbone.View.extend({
        el: $('body'), //el attaches to existing element <-- what does this mean?
        events: {
            'click button#addSetButton': 'addSet'
        },
        initialize: function(){
            alert('initialize called in allsetview');
            _.bindAll(this,'renderAllSet', 'addSet', 'appendSet');
            this.collection = new SetCollection();
            this.collection.bind('add', this.appendSet); // Problem here...
            this.counter = 0;
            this.renderAllSet(); 
        },
        renderAllSet: function(){
            alert('renderallset called in allsetview');
            var self = this; 
            $(this.el).append('<button id="addSetButton"> Add Set </button>');
            $(this.el).append('<ul></ul>');
            _(this.collection.models).each(function(set){ //in case collection is not empty
                self.appendSet(set);
            },this); 
        },
        addSet: function(){
            alert('addSet called in allsetview');
            this.counter++;
            var thisSet = new Set();
            thisSet.set({SetName:thisSet.get('SetName')+this.counter});
            this.collection.add(thisSet); //add is a function defined for the collection
        },
        appendSet: function(item){
            alert("append set called in allsetview");
            var setView = new SetView({
                model: Set //DO NOT CAPITALIZE!!!... or do capitalize?... ack
            });
            $('ul',this.el).append(setView.renderSet().el);
        }
    });

    var allsetview = new AllSetView(); //for testing

    var Item = Backbone.Model.extend({
        defaults: {
            ItemName: 'Enter an Item'
            //more properties
        },
        initialize: function(){
            alert('youve created a new item');
            var set1 = new Set();
            var setCollection = new SetCollection([set1]);
            this.set({sets:setCollection});
            this.bind("error",function(model,error){
                alert(error);
            });
        }
    });

    var ItemCollection = Backbone.Collection.extend({
        model:Item
    });

    var ItemView = Backbone.View.extend({
        events: {
            'click button.deleteItem': 'removeItem'
        },
        initialize: function(){
            alert('initialize called in itemview');
            _.bindAll(this,'renderItem', 'unrenderItem', 'removeItem');
            //this.model.bind('change',this.renderItem);
            //this.model.bind('remove',this.unrender); Not sure if I should do this
            return this; //apparently for chainable calls    
        },
        renderItem: function(){
            alert('renderitem called in Itemview');
            $(this.el).html('an item template'); //add button after so you can test delete
            return this;
        },
        unrenderItem: function(){
            alert('unrenderitem called in itemview');
            $(this.el).remove();
        },
        removeItem: function(){
            alert('removeItem called in itemview');
            this.model.destroy();
        }
    });

    alert ("before itemview creation");
    var itemview = new ItemView();
    alert ("now after");

    var AllItemView = Backbone.View.extend({
        el: $('body'), //el attaches to existing element <-- what does this mean?
        events: {
            'click button#addItemButton': 'addItem'
        },
        initialize: function(){
            alert('initialize called in allitemview');
            _.bindAll(this,'renderAllItem', 'addItem', 'appendItem');
            this.collection = new ItemCollection();
            this.collection.bind('add', this.appendItem); //Problem here
            this.counter = 0;
            this.renderAllItem(); 
        },
        renderAllItem: function(){
            alert('renderallitem called in allitemview');
            var self = this; //why
            $(this.el).append('<button id="addItemButton"> Add Item </button>');
            $(this.el).append('<ul></ul>');
            _(this.collection.models).each(function(item){ //in case collection is not empty
                self.appendItem(item);
            },this); //what is this function
        },
        addItem: function(){
            alert('addItem called in allitemview');
            this.counter++;
            var thisItem = new Item();
            thisItem.item({ItemName:thisItem.get('ItemName')+this.counter
            });
            this.collection.add(thisItem); //add is a function defined for the collection
            this.appendItem(thisItem);
        },
        appendItem: function(item){
            alert("append item called in allItemview");
            var itemView = new ItemView({
                model: Item //DO NOT CAPITALIZE!!!... or do capitalize?... 
            });
            $('ul',this.el).append(itemView.renderItem().el);
        }
    });
})(jQuery);