In meiner Webanwendung habe ich links eine Benutzerliste in einer Tabelle und rechts einen Benutzerdetailbereich. Wenn der Administrator auf einen Benutzer in der Tabelle klickt, sollten dessen Details rechts angezeigt werden.
Ich habe links eine UserListView und UserRowView und rechts eine UserDetailView. Die Dinge funktionieren, aber ich habe ein komisches Verhalten. Wenn ich links auf einige Benutzer klicke und dann auf einen von ihnen klicke, werden nacheinander Javascript-Bestätigungsfelder für alle angezeigten Benutzer angezeigt.
Es sieht so aus, als ob Ereignisbindungen aller zuvor angezeigten Ansichten nicht entfernt wurden, was normal zu sein scheint. Ich sollte nicht jedes Mal eine neue UserDetailView in UserRowView erstellen. Sollte ich eine Ansicht beibehalten und das Referenzmodell ändern? Sollte ich die aktuelle Ansicht verfolgen und entfernen, bevor ich eine neue erstelle? Ich bin irgendwie verloren und jede Idee wird willkommen sein. Danke !
Hier ist der Code der linken Ansicht (Zeilenanzeige, Klickereignis, Erstellung der rechten Ansicht)
window.UserRowView = Backbone.View.extend({
tagName : "tr",
events : {
"click" : "click",
},
render : function() {
$(this.el).html(ich.bbViewUserTr(this.model.toJSON()));
return this;
},
click : function() {
var view = new UserDetailView({model:this.model})
view.render()
}
})
Und der Code für die rechte Ansicht (Schaltfläche Löschen)
window.UserDetailView = Backbone.View.extend({
el : $("#bbBoxUserDetail"),
events : {
"click .delete" : "deleteUser"
},
initialize : function() {
this.model.bind('destroy', function(){this.el.hide()}, this);
},
render : function() {
this.el.html(ich.bbViewUserDetail(this.model.toJSON()));
this.el.show();
},
deleteUser : function() {
if (confirm("Really delete user " + this.model.get("login") + "?"))
this.model.destroy();
return false;
}
})
quelle
delete view
im Router?Ich zerstöre und erstelle immer Ansichten, da es schwierig wird, nicht verwendete Live-Ansichten im Speicher zu behalten, damit meine wiederverwendbaren Ansichten immer größer werden, damit ich sie wiederverwenden kann.
Hier ist eine vereinfachte Version einer Technik, mit der ich meine Ansichten bereinige, um Speicherlecks zu vermeiden.
Ich erstelle zuerst eine BaseView, von der alle meine Ansichten erben. Die Grundidee ist, dass meine Ansicht einen Verweis auf alle Ereignisse enthält, die sie abonniert hat, sodass alle diese Bindungen automatisch ungebunden sind, wenn es Zeit ist, die Ansicht zu entsorgen. Hier ist eine Beispielimplementierung meiner BaseView:
Wann immer eine Ansicht an ein Ereignis in einem Modell oder einer Sammlung gebunden werden muss, verwende ich die bindTo-Methode. Beispielsweise:
Immer wenn ich eine Ansicht entferne, rufe ich einfach die dispose-Methode auf, die alles automatisch bereinigt:
Ich habe diese Technik mit den Leuten geteilt, die das E-Book "Backbone.js on Rails" schreiben, und ich glaube, dies ist die Technik, die sie für das Buch übernommen haben.
Update: 24.03.2014
Ab Backone 0.9.9 wurden ListenTo und StopListening zu Ereignissen hinzugefügt, wobei dieselben oben gezeigten Techniken bindTo und unbindFromAll verwendet wurden. Außerdem ruft View.remove stopListening automatisch auf, sodass das Binden und Aufheben der Bindung jetzt so einfach ist:
quelle
Dies ist eine häufige Erkrankung. Wenn Sie jedes Mal eine neue Ansicht erstellen, werden alle alten Ansichten weiterhin an alle Ereignisse gebunden. Sie können in Ihrer Ansicht eine Funktion mit dem Namen erstellen
detatch
:Stellen Sie dann sicher, dass Sie anrufen, bevor Sie die neue Ansicht erstellen
detatch
die alte Ansicht .Wie Sie bereits erwähnt haben, können Sie natürlich immer eine "Detail" -Ansicht erstellen und diese niemals ändern. Sie können an das Ereignis "Ändern" im Modell (aus der Ansicht) binden, um sich selbst neu zu rendern. Fügen Sie dies Ihrem Initialisierer hinzu:
Dadurch wird das Detailfenster jedes Mal neu gerendert, wenn eine Änderung am Modell vorgenommen wird. Sie können eine feinere Granularität erzielen, indem Sie nach einer einzelnen Eigenschaft suchen: "change: propName".
Dazu ist natürlich ein allgemeines Modell erforderlich, auf das sich die Elementansicht bezieht, sowie die Listenansicht auf höherer Ebene und die Detailansicht.
Hoffe das hilft!
quelle
this.model.unbind()
für mich falsch, weil es alle Ereignisse aus diesem Modell aufhebt, einschließlich Ereignisse in Bezug auf andere Ansichten desselben Benutzers. Um diedetach
Funktion aufzurufen , muss ich außerdem einen statischen Verweis auf die Ansicht behalten, und das gefällt mir nicht. Ich vermute, es gibt noch etwas, das ich nicht verstanden habe ...Um mehrfach bindende Ereignisse zu beheben,
Durch die Verwendung der obigen Zeile vor dem Instanziieren der neuen Ansichten von der Route wurde das Problem mit Zombie-Ansichten behoben.
quelle
Ich denke, die meisten Leute, die mit Backbone beginnen, erstellen die Ansicht wie in Ihrem Code:
Dieser Code erstellt eine Zombie-Ansicht, da wir möglicherweise ständig eine neue Ansicht erstellen, ohne die vorhandene Ansicht zu bereinigen. Es ist jedoch nicht bequem, view.dispose () für alle Backbone-Ansichten in Ihrer App aufzurufen (insbesondere, wenn wir Ansichten in for-Schleife erstellen).
Ich denke, der beste Zeitpunkt, um Bereinigungscode einzufügen, ist vor dem Erstellen einer neuen Ansicht. Meine Lösung besteht darin, einen Helfer für diese Bereinigung zu erstellen:
Durch die Verwendung von VM zum Erstellen Ihrer Ansicht können Sie vorhandene Ansichten bereinigen, ohne view.dispose () aufrufen zu müssen. Sie können eine kleine Änderung an Ihrem Code vornehmen
zu
Es liegt also an Ihnen, ob Sie die Ansicht wiederverwenden möchten, anstatt sie ständig zu erstellen. Solange die Ansicht sauber ist, müssen Sie sich keine Sorgen machen. Ändern Sie einfach createView in reuseView:
Detaillierte Informationen zu Code und Zuordnung finden Sie unter https://github.com/thomasdao/Backbone-View-Manager
quelle
Eine Alternative besteht darin, zu binden, anstatt eine Reihe neuer Ansichten zu erstellen und diese Ansichten dann zu lösen. Sie würden dies erreichen, indem Sie Folgendes tun:
Sie würden das Modell von myView auf myViewModel setzen, das auf ein Benutzermodell gesetzt würde. Wenn Sie myViewModel auf einen anderen Benutzer festlegen (dh dessen Attribute ändern), kann auf diese Weise eine Renderfunktion in der Ansicht mit den neuen Attributen ausgelöst werden.
Ein Problem ist, dass dadurch die Verbindung zum Originalmodell unterbrochen wird. Sie können dies umgehen, indem Sie entweder ein Sammlungsobjekt verwenden oder das Benutzermodell als Attribut des Ansichtsmodells festlegen. Dann wäre dies in der Ansicht als myview.model.get ("Modell") zugänglich.
quelle
Verwenden Sie diese Methode, um die untergeordneten Ansichten und aktuellen Ansichten aus dem Speicher zu löschen.
quelle