Ich baue Funktionen auf eine Webseite, die der Benutzer mehrmals ausführen kann. Durch die Aktion des Benutzers wird ein Objekt / Modell erstellt und mit ko.applyBindings () auf HTML angewendet.
Der datengebundene HTML-Code wird über jQuery-Vorlagen erstellt.
So weit, ist es gut.
Wenn ich diesen Schritt wiederhole, indem ich ein zweites Objekt / Modell erstelle und ko.applyBindings () aufrufe, treten zwei Probleme auf:
- Das Markup zeigt das vorherige Objekt / Modell sowie das neue Objekt / Modell.
- Ein Javascript-Fehler tritt in Bezug auf eine der Eigenschaften im Objekt / Modell auf, obwohl er immer noch im Markup gerendert wird.
Um dieses Problem zu umgehen, rufe ich nach dem ersten Durchgang jempty .empty () auf, um das HTML-Vorlagen zu entfernen, das alle Datenbindungsattribute enthält, sodass es nicht mehr im DOM enthalten ist. Wenn der Benutzer den Prozess für den zweiten Durchgang startet, wird der datengebundene HTML-Code erneut zum DOM hinzugefügt.
Aber wie gesagt, wenn der HTML-Code erneut zum DOM hinzugefügt und an das neue Objekt / Modell neu gebunden wird, enthält er immer noch Daten vom ersten Objekt / Modell, und ich erhalte immer noch den JS-Fehler, der nicht auftritt während des ersten Durchgangs.
Die Schlussfolgerung scheint zu sein, dass Knockout an diesen gebundenen Eigenschaften festhält, obwohl das Markup aus dem DOM entfernt wurde.
Ich suche also nach einem Mittel, um diese gebundenen Eigenschaften aus Knockout zu entfernen. Knockout sagen, dass es kein beobachtbares Modell mehr gibt. Gibt es eine Möglichkeit, dies zu tun?
BEARBEITEN
Der grundlegende Prozess besteht darin, dass der Benutzer eine Datei hochlädt. Der Server antwortet dann mit einem JSON-Objekt. Der datengebundene HTML-Code wird dem DOM hinzugefügt. Anschließend wird das JSON-Objektmodell mithilfe von an diesen HTML-Code gebunden
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
Sobald der Benutzer einige Auswahlen für das Modell getroffen hat, wird dasselbe Objekt auf den Server zurückgesendet, der datengebundene HTML-Code wird aus dem DOM entfernt, und ich habe dann das folgende JS
mn.AccountCreationModel = null;
Wenn der Benutzer dies noch einmal tun möchte, werden alle diese Schritte wiederholt.
Ich fürchte, der Code ist zu "involviert", um eine jsFiddle-Demo zu erstellen.
init
Funktion verfügbar machen , in der Sie die anzuwendenden Daten übergeben?Antworten:
Haben Sie versucht, die Clean Node-Methode von Knockout für Ihr DOM-Element aufzurufen, um die im Speicher gebundenen Objekte zu entsorgen?
Wenn Sie dann die Knockout-Bindungen mit Ihren neuen Ansichtsmodellen erneut auf genau dieses Element anwenden, wird Ihre Ansichtsbindung aktualisiert.
quelle
delete
entnehmen kann, werden bestimmte Schlüssel für die dom-Elemente selbst aufgerufen, in denen anscheinend die gesamte Knockout-Magie gespeichert ist. Wenn jemand eine Quelle für Dokumentation hat, wäre ich sehr dankbar.Für ein Projekt, an dem ich arbeite, habe ich eine einfache
ko.unapplyBindings
Funktion geschrieben, die einen jQuery-Knoten und den Booleschen Wert zum Entfernen akzeptiert. Zuerst werden alle jQuery-Ereignisse aufgehoben, da sich dieko.cleanNode
Methode nicht darum kümmert. Ich habe auf Speicherlecks getestet und es scheint gut zu funktionieren.quelle
ko.cleanNode()
aufgerufen wurde , nicht getestet und nicht das gesamte HTML ersetzt.Sie können versuchen, die mit Knockout angebotene Bindung zu verwenden : http://knockoutjs.com/documentation/with-binding.html Die Idee ist, einmalige Bindungsbindungen zu verwenden. Wenn sich Ihre Daten ändern, aktualisieren Sie einfach Ihr Modell.
Nehmen wir an, Sie haben ein Ansichtsmodell der obersten Ebene storeViewModel, Ihren von cartViewModel dargestellten Warenkorb und eine Liste der Artikel in diesem Warenkorb - beispielsweise cartItemsViewModel.
Sie würden das Modell der obersten Ebene - das storeViewModel - an die gesamte Seite binden. Anschließend können Sie die Teile Ihrer Seite trennen, die für den Warenkorb oder die Warenkorbartikel verantwortlich sind.
Nehmen wir an, dass cartItemsViewModel die folgende Struktur hat:
Das cartItemsViewModel kann am Anfang leer sein.
Die Schritte würden so aussehen:
Definieren Sie Bindungen in HTML. Trennen Sie die cartItemsViewModel-Bindung.
Das Geschäftsmodell stammt von Ihrem Server (oder wird auf andere Weise erstellt).
var storeViewModel = ko.mapping.fromJS(modelFromServer)
Definieren Sie leere Modelle in Ihrem Ansichtsmodell der obersten Ebene. Dann kann eine Struktur dieses Modells mit tatsächlichen Daten aktualisiert werden.
Binden Sie das Ansichtsmodell der obersten Ebene.
ko.applyBindings(storeViewModel);
Wenn das cartItemsViewModel-Objekt verfügbar ist, weisen Sie es dem zuvor definierten Platzhalter zu.
storeViewModel.cartItemsViewModel(actualCartItemsModel);
Wenn Sie die Warenkorbartikel löschen möchten:
storeViewModel.cartItemsViewModel(null);
Knockout kümmert sich um HTML - dh es wird angezeigt, wenn das Modell nicht leer ist und der Inhalt von div (der mit dem "mit Bindung") verschwindet.
quelle
Ich muss ko.applyBinding jedes Mal aufrufen, wenn auf die Schaltfläche klicken, und gefilterte Daten werden vom Server zurückgegeben. In diesem Fall kann ich nach der Arbeit für mich arbeiten, ohne ko.cleanNode zu verwenden.
Ich habe erfahren, wenn wir foreach durch template ersetzen, sollte es bei Sammlungen / ObservableArray gut funktionieren.
Dieses Szenario ist möglicherweise hilfreich.
quelle
Statt KO interne Funktionen zu nutzen und mit JQuery der Decke Ereignishandler Entfernung zu tun, eine viel bessere Idee verwendet
with
odertemplate
Bindungen. Wenn Sie dies tun, erstellt ko diesen Teil des DOM neu und es wird automatisch bereinigt. Dies wird auch empfohlen, siehe hier: https://stackoverflow.com/a/15069509/207661 .quelle
Ich denke, es ist vielleicht besser, die Bindung die ganze Zeit beizubehalten und einfach die damit verbundenen Daten zu aktualisieren. Ich bin auf dieses Problem gestoßen und habe festgestellt, dass das Aufrufen der
.resetAll()
Methode auf dem Array, in dem ich meine Daten gespeichert habe, der effektivste Weg ist, dies zu tun.Grundsätzlich können Sie mit einer globalen Variable beginnen, die Daten enthält, die über das ViewModel gerendert werden sollen:
Es dauerte eine Weile, bis mir klar wurde, dass ich nicht einfach
myLiveData
ein normales Array erstellen konnte - derko.oberservableArray
Teil war wichtig.Dann können Sie weitermachen und tun, was Sie wollen
myLiveData
. Zum Beispiel macht einen$.getJSON
Anruf:Sobald Sie dies getan haben, können Sie wie gewohnt Bindungen mit Ihrem ViewModel anwenden:
Dann im HTML einfach so verwenden,
myData
wie Sie es normalerweise tun würden.Auf diese Weise können Sie einfach mit myLiveData von jeder Funktion aus Mist spielen. Wenn Sie beispielsweise alle paar Sekunden aktualisieren möchten, schließen Sie diese
$.getJSON
Zeile einfach in eine Funktion ein und rufen SiesetInterval
sie auf. Sie müssen die Bindung niemals entfernen, solange Sie daran denken, diemyLiveData.removeAll();
Linie beizubehalten.Wenn Ihre Daten nicht wirklich riesig sind, können Benutzer nicht einmal die Zeit zwischen dem Zurücksetzen des Arrays und dem erneuten Hinzufügen der aktuellsten Daten bemerken.
quelle
Ich hatte kürzlich ein Problem mit Speicherverlusten und
ko.cleanNode(element);
würde es nicht für mich tun -ko.removeNode(element);
tat es. Javascript + Knockout.js Speicherverlust - Wie kann sichergestellt werden, dass ein Objekt zerstört wird?quelle
Haben Sie darüber nachgedacht:
Ich habe mir das ausgedacht, weil ich in Knockout diesen Code gefunden habe
Für mich ist es also nicht wirklich ein Problem, das bereits gebunden ist, sondern dass der Fehler nicht abgefangen und behoben wurde ...
quelle
Ich habe festgestellt, dass, wenn das Ansichtsmodell viele Div-Bindungen enthält, der beste Weg zum Löschen der folgenden
ko.applyBindings(new someModelView);
ist:ko.cleanNode($("body")[0]);
Dies ermöglicht es Ihnen, ein neuesko.applyBindings(new someModelView2);
dynamisch aufzurufen , ohne dass das vorherige Ansichtsmodell noch gebunden werden muss.quelle
$("body")[0]
istdocument.body
.