2012-03-26 4 views
5

Ich habe den folgenden Code:Backbone diese Verwirrung

var GoalPanelView = Backbone.View.extend({ 

    // Bind to the goal panel DOM element 
    el: $("#sidebar-goals"),  

    // Initialize the collection 
    initialize: function() { 
     this.collection = Goals; 
     this.collection.bind('add', this.appendItem); 
    }, 

    // Create a new goal when a user presses enter in the enter goal input 
    createOnEnter: function(e) { 
     if (e.keyCode != 13) return; 
     this.addItem(); 
     //Goals.create(this.newAttributes());   
    }, 

    // Add the goal item to the goal list 
    addItem: function() { 
     var goal = new Goal(); 
     goal.set(this.newAttributes()); 
     var goalsElem = this.el; 
     this.collection.add(goal); 
     $(this.el).children("#enter-goal").val(''); 
    }, 

    // Append DOM element to the parent el 
    appendItem: function(item) { 
     var goalView = new GoalView({ 
      model: item, 
     }); 
     $(this.elem).append(goalView.render().el); 
    } 

}); 

Mein Problem ist, innerhalb der appendItem Funktion. Wenn ich this innerhalb der appendItem Funktion verwende, glaube ich, dass es denkt, dass die this sich auf die this.collection eher als die GoalPanelView bezieht. Wie würde ich die this beziehen sich auf die GoalPanelView anstelle der collection? Ich habe versucht, eine andere Variable in die appendItem Funktion übergeben, die den Inhalt von this.elem enthielt, aber es schien nicht zu funktionieren.

Eine Sache, die arbeitete, war, als ich die appendItem Funktion in die collection bewegte und verändern die Initialisierung this.collection.bind('add', appendItem); zu binden, aber ich will nicht die view Sachen in die collection Logik setzen.

+2

Eine Alternative ist '_.bindAll (this)' in Ihre Initialisierungsfunktion zu setzen. Dies stellt sicher, dass jede Funktion, die innerhalb des Objekts aufgerufen wird, mit dem Wert "this" verknüpft wird, der ordnungsgemäß an das Objekt selbst gebunden ist. Nützlich, wenn Sie viele Rückrufe schreiben. – rybosome

Antwort

6

können Sie einen Rahmen hinzu, wenn ein Event-Handler-Bindung, etwa so:

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

Der Umfang setzt den Wert von this innerhalb des Handlers. In diesem Fall das aktuelle Objekt.

Edit:Javascript Garden eine große explaination hat, warum this.appendItem eigentlich nicht den Umfang der Funktion selbst tragen, es ist nur ein Funktionszeiger, kein Verfahren Zeiger. Einer der Macken von Javascript ..

bearbeiten 2Backbone Reference - Events/on

0

Sie auch _.bindAll Funktion in Ihrem initialize Methode des Unterstreichungs verwenden können:

initialize: function() { 
    _.bindAll(this); 
    this.collection = Goals; 
    this.collection.bind('add', this.appendItem); 
} 

Nun kann jeder Aufruf von Methoden auf GoalPanelView (zB appendItem) wird so festgelegt, dass Verweise auf this auf die GoalPanelView Instanz verweisen.

Sie können auch in einer Liste von Methodennamen als Zeichenfolge übergeben, wenn Sie alle Methoden der nicht wollen, GoalPanelView zu Umfang

Siehe hier: http://underscorejs.org/#bindAll

2

einfach zu aktualisieren (Stand Backbone 0,9. 2), der richtige Weg, dies zu tun ist:

initialize: function() { 
    this.collection.on("add", this.appendItem, this); 
    ... 
} 


auf Ihren Anwendungsfall abhängig, Sie können ein Auch zu berücksichtigen:

initialize: function() { 
    this.listenTo(this.collection, "add", this.appendItem); 
    ... 
} 
+0

Dies ist der richtige Weg, es zu tun –

+1

Eigentlich wäre es besser, "this.listenTo" zu verwenden, so dass das Aufheben des Ereignisses automatisch beim Aufruf von remove geschieht. Auf diese Weise verhindern Sie Speicherlecks. –