Also hier ist ein seltsames KnockoutJS Problem, das ich noch nie zuvor gesehen habe.Knockout JS löscht keine Komponenten
Ich arbeite an einer Anwendung, die Knockout-Komponenten sehr stark verwendet.
In einem Teil der App habe ich eine Editor-Seite, die dynamisch von einem JSON-basierten Backend erstellt wird und die eine Frontend-Seite mit einer Anzahl von Widgets belegt, abhängig davon, was aus den Back-End-Daten erzählt wird.
Beispiel Das hintere Ende könnte senden
[{"widget": "textBox"},{"widget": "textBox"},{"widget": "comboBox"},{"widget": "checkBox"}]
die das vordere Ende führen würde eine Seite mit
<html>
....
<textbox></textbox>
<textbox></textbox>
<combobox></combobox>
<checkbox></checkbox>
....
</html>
Jede der benutzerdefinierten Tags aufzubauen ist eine individuelle KnockoutJS Komponente, zusammengestellt als ein AMD-Modul und geladen mit RequireJS, jede Komponente basiert auf der gleichen Boiler-Platte:
Die Komponenten kommunizieren miteinander und mit der Seite unter Verwendung von "Knockout Postbox" in einer Pub Sub Mode.
Und wenn ich sie in die Seite, die ich so in den folgenden Herren tun:
<div data-bind="foreach: pageComponentsToDisplay">
<!-- ko if: widget == "textBox" -->
<textBox params="details: $data"></textBox>
<!-- /ko -->
<!-- ko if: widget == "comboBox" -->
<comboBox params="details: $data"></comboBox>
<!-- /ko -->
<!-- ko if: widget == "checkBox" -->
<checkBox params="details: $data"></checkBox>
<!-- /ko -->
</div>
und wo pageComponentsToDisplay einen einfachen KO-beobachtbaren Array, das schiebe ich nur die Objekte aus dem Backend erhielten auf:
pageComponentsToDisplay = ko.observableArray([]);
pageComponentsToDisplay(data);
Wo ‚Daten‘ wie oben
nun all dies funktioniert gut, aber hier in liegt nun das ODD in JSON gezeigt.
Wenn ich ein „reload“ der Seite zu tun, habe ich einfach
pageComponentsToDisplay = ko.observableArray([]);
das Array zu löschen und damit alle meine Komponenten auch von der Seite verschwinden, wie erwartet, aber wenn ich lade die neuen Daten in wieder mit:
pageComponentsToDisplay(data);
ich meine neue Komponenten auf dem Bildschirm erhalten, wie erwartet, aber die alten erscheinen nach wie vor vorhanden und aktiv im Speicher zu sein, auch wenn es nicht sichtbar.
Der Grund, warum ich die Steuerelemente kenne, ist immer noch da, denn wenn ich eine meiner PubSub-Nachrichten ausstelle, um die Steuerelemente nach Statusinformationen zu fragen, antworten ALLE.
Es scheint mir, dass wenn ich das Array lösche, und wenn KO das Ansichtsmodell löscht, scheint es nicht wirklich die alten Kopien zu zerstören.
Weiter, wenn ich wieder auffrischen, bekomme ich dann 3 Sätze von Komponenten reagieren, aktualisieren Sie erneut und es ist 4, und dies erhöht sich wie erwartet.
Dies ist das erste Mal, dass ich dieses Verhalten mit Knockout habe, und ich habe diese Art von Muster seit Jahren ohne ein Problem verwendet.
Wenn Sie einen guten Überblick über wollen, wie das gesamte Projekt eingerichtet ist, habe ich eine Probe Skelett Layout auf meiner GitHub Seite:
https://github.com/shawty/dotnetnotts15
Wenn jemand irgendwelche Ideen auf, hat das, was hier passiert sein könnte Ich würde sie gerne hören.
Als letzte Anmerkung entwickle ich eigentlich alles mit Typescript, aber da dies ein Laufzeitproblem ist, dokumentiere ich es aus Sicht von JS.
Grüße Shawty
Update 1
So nach Graben weiter (und mit einem wenig ‚neuen Denken‘ dank cl3m Antwort) Ich bin ein wenig weiter nach vorne.
In meinem ersten Post habe ich erwähnt, dass ich Ryan Niemeyers excellente PubSub Erweiterung für Knockout 'ko Postbox' verwendet.
Es stellt sich heraus, dass meine 'Komponenten' entsorgt und abgerissen werden, ABER die Subskriptions-Handler, die erstellt werden, um auf Postfach zu reagieren, sind nicht.
Das Ergebnis ist, dass die VM (oder genauer gesagt die Werte, die das Abonnement in der VM verwendet) zusammen mit dem Postbox-Abonnement-Handler im Speicher gehalten werden.
Das bedeutet, wenn mein Master eine Nachricht sendet, die nach Komponentenwerten fragt, antwortet die gehaltene Referenz, gefolgt von der sichtbar aktiven Komponente.
Was ich jetzt tun muss, ist eine Möglichkeit, diese Subskriptionen zu disponieren, die, weil ich Postbox direkt benutze und sie keinem Observablen in meinem Modell zuordne, bedeutet, dass ich nicht wirklich ein var oder habe Objektreferenz, um sie anzusprechen.
Die Suche geht weiter.
Update 2
unten auf die Frage meiner Selbst Antwort sehen.
Verwenden Sie die Methode 'ko.utils.domNodeDisposal.addDisposeCallback()', um Ihre Knockout-Komponenten zu entfernen, nachdem die entsprechenden Elemente aus dem 'DOM' entfernt wurden? – cl3m
Nicht, dass ich mir bewusst, ich lösche nur das Array und ich nahm an, dass die Instanzen meiner Komponenten automatisch riss. Ich muss jedoch gestehen, als ich dies am Freitag recherchiert habe, bin ich auf die Dokumente gestoßen, die es erwähnt haben, aber ich habe es noch nicht benutzt. Kurz gesagt, wenn KO es nicht automatisch für mich macht, dann NEIN, ich bin es nicht. – shawty
Ich verwende diese Methode für benutzerdefinierte Bindungen, ich dit es nicht auf Komponenten aber ... – cl3m