Buduję funkcjonalność na stronie internetowej, którą użytkownik może wykonywać wielokrotnie. W wyniku działania użytkownika obiekt / model jest tworzony i stosowany do HTML za pomocą ko.applyBindings ().
Powiązany z danymi kod HTML jest tworzony za pomocą szablonów jQuery.
Na razie w porządku.
Kiedy powtarzam ten krok, tworząc drugi obiekt / model i wywołując ko.applyBindings (), napotykam dwa problemy:
- Znacznik pokazuje poprzedni obiekt / model, a także nowy obiekt / model.
- Występuje błąd javascript dotyczący jednej z właściwości w obiekcie / modelu, mimo że jest nadal renderowany w znaczniku.
Aby obejść ten problem, po pierwszym przejściu wywołuję .empty () jQuery, aby usunąć szablon HTML zawierający wszystkie atrybuty wiązania danych, tak aby nie był już w DOM. Gdy użytkownik rozpoczyna proces dla drugiego przebiegu, związany z danymi kod HTML jest ponownie dodawany do DOM.
Ale tak jak powiedziałem, kiedy kod HTML jest ponownie dodawany do DOM i ponownie powiązany z nowym obiektem / modelem, nadal zawiera dane z pierwszego obiektu / modelu i nadal otrzymuję błąd JS, który nie występuje podczas pierwszego przejazdu.
Wniosek wydaje się być taki, że Knockout zachowuje te powiązane właściwości, mimo że znaczniki są usuwane z DOM.
Więc to, czego szukam, to sposób na usunięcie tych powiązanych właściwości z Knockout; mówiąc nokaut, że nie ma już obserwowalnego modelu. Czy jest na to sposób?
EDYTOWAĆ
Podstawowy proces polega na tym, że użytkownik przesyła plik; serwer odpowiada następnie obiektem JSON, kod HTML powiązany z danymi jest dodawany do DOM, a następnie model obiektowy JSON jest powiązany z tym kodem HTML za pomocą
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
Gdy użytkownik dokona pewnych wyborów w modelu, ten sam obiekt jest wysyłany z powrotem na serwer, kod HTML powiązany z danymi jest usuwany z DOM, a następnie mam następujący kod JS
mn.AccountCreationModel = null;
Gdy użytkownik chce to zrobić jeszcze raz, wszystkie te kroki są powtarzane.
Obawiam się, że kod jest zbyt „zaangażowany”, aby wykonać demo jsFiddle.
init
funkcji, w której przekazujesz dane do zastosowania?Odpowiedzi:
Czy próbowałeś wywołać metodę czyszczenia węzła knockout w elemencie DOM, aby pozbyć się obiektów związanych z pamięcią?
Następnie ponowne zastosowanie powiązań odcinania tylko na tym elemencie z nowymi modelami widoku zaktualizowałoby powiązanie widoku.
źródło
delete
on pewne klucze na samych elementach dom, w których najwyraźniej przechowywana jest cała magia nokautu. Jeśli ktoś ma źródło w dokumentacji, byłbym bardzo zobowiązany.Dla projektu, nad którym pracuję, napisałem prostą
ko.unapplyBindings
funkcję, która akceptuje węzeł jQuery i wartość logiczną remove. Najpierw rozwiązuje wszystkie zdarzenia jQuery, ponieważko.cleanNode
metoda o to nie robi. Testowałem pod kątem wycieków pamięci i wydaje się, że działa dobrze.źródło
ko.cleanNode()
wywołane, a nie zastąpiono całego kodu HTML.Możesz spróbować użyć powiązania z wiązaniem, które oferuje knockout: http://knockoutjs.com/documentation/with-binding.html Chodzi o to, aby użyć zastosuj powiązania raz i za każdym razem, gdy zmienią się twoje dane, po prostu zaktualizuj model.
Załóżmy, że masz model widoku najwyższego poziomu storeViewModel, Twój koszyk reprezentowany przez cartViewModel i listę elementów w tym koszyku - powiedzmy cartItemsViewModel.
Powiążesz model najwyższego poziomu - storeViewModel z całą stroną. Następnie możesz oddzielić części strony, które są odpowiedzialne za koszyk lub elementy koszyka.
Załóżmy, że cartItemsViewModel ma następującą strukturę:
CartItemsViewModel może być na początku pusty.
Kroki wyglądałyby następująco:
Zdefiniuj wiązania w html. Oddziel powiązanie cartItemsViewModel.
Model sklepu pochodzi z Twojego serwera (lub jest tworzony w inny sposób).
var storeViewModel = ko.mapping.fromJS(modelFromServer)
Zdefiniuj puste modele w modelu widoku najwyższego poziomu. Następnie strukturę tego modelu można zaktualizować o rzeczywiste dane.
Powiąż model widoku najwyższego poziomu.
ko.applyBindings(storeViewModel);
Gdy obiekt cartItemsViewModel jest dostępny, przypisz go do wcześniej zdefiniowanego symbolu zastępczego.
storeViewModel.cartItemsViewModel(actualCartItemsModel);
Jeśli chcesz wyczyścić pozycje z koszyka:
storeViewModel.cartItemsViewModel(null);
Knockout zajmie się html - czyli pojawi się, gdy model nie jest pusty, a zawartość div (ta z "z wiązaniem") zniknie.
źródło
Muszę wywoływać ko.applyBinding za każdym razem, gdy kliknę przycisk wyszukiwania, a przefiltrowane dane wracają z serwera, aw tym przypadku dalsza praca u mnie bez użycia ko.cleanNode.
Doświadczyłem, że jeśli zastąpimy foreach szablonem, to powinno działać dobrze w przypadku collections / observableArray.
Ten scenariusz może być przydatny.
źródło
Zamiast używać funkcji wewnętrznych KO i zajmować się usuwaniem modułu obsługi zdarzeń JQuery, znacznie lepszym pomysłem jest użycie
with
lubtemplate
powiązania. Gdy to zrobisz, ko odtwarza tę część DOM, dzięki czemu jest ona automatycznie czyszczona. Jest to również zalecany sposób, patrz tutaj: https://stackoverflow.com/a/15069509/207661 .źródło
Myślę, że lepiej byłoby zachować powiązanie przez cały czas i po prostu zaktualizować powiązane z nim dane. Napotkałem ten problem i stwierdziłem, że po prostu dzwonię przy użyciu
.resetAll()
metody z tablicy, w której przechowywałem dane, było najefektywniejszym sposobem na zrobienie tego.Zasadniczo możesz zacząć od globalnej zmiennej, która zawiera dane do renderowania za pośrednictwem ViewModel:
Zajęło mi trochę czasu, zanim zdałem sobie sprawę, że nie mogę po prostu zrobić
myLiveData
zwykłej tablicy - tako.oberservableArray
część była ważna.Wtedy możesz iść dalej i robić, co chcesz
myLiveData
. Na przykład$.getJSON
zadzwoń:Gdy to zrobisz, możesz normalnie zastosować wiązania za pomocą swojego ViewModel:
Następnie w kodzie HTML użyj
myData
tak, jak zwykle.W ten sposób możesz po prostu pomieszać z myLiveData z dowolnej funkcji. Na przykład, jeśli chcesz aktualizować co kilka sekund, po prostu zawiń tę
$.getJSON
linię w funkcję i wywołajsetInterval
ją. Nigdy nie będziesz musiał zdejmować wiązania, o ile będziesz pamiętać o utrzymaniumyLiveData.removeAll();
żyłki.O ile twoje dane nie są naprawdę ogromne, użytkownik nie będzie nawet w stanie zauważyć czasu między zresetowaniem macierzy a ponownym dodaniem najbardziej aktualnych danych.
źródło
Niedawno miałem problem z wyciekiem pamięci i
ko.cleanNode(element);
nie zrobiłbym tego za mnie -ko.removeNode(element);
tak. Wyciek pamięci Javascript + Knockout.js - Jak upewnić się, że obiekt jest niszczony?źródło
Czy myślałeś o tym:
Wymyśliłem to, ponieważ w Knockout znalazłem ten kod
Więc dla mnie to nie jest tak naprawdę problem, który jest już związany, to że błąd nie został złapany i rozwiązany ...
źródło
Zauważyłem, że jeśli model widoku zawiera wiele powiązań div, najlepszym sposobem na wyczyszczenie
ko.applyBindings(new someModelView);
jest użycie:ko.cleanNode($("body")[0]);
Pozwala to nako.applyBindings(new someModelView2);
dynamiczne wywoływanie nowego bez obawy, że poprzedni model widoku nadal jest powiązany.źródło
$("body")[0]
jestdocument.body
.