Z dokumentów:
DetectChanges (): void
Sprawdza detektor zmian i jego elementy podrzędne.
Oznacza to, że jeśli jest przypadek, w którym coś w twoim modelu (twojej klasie) uległo zmianie, ale nie odzwierciedlało widoku, może być konieczne powiadomienie Angulara, aby wykrył te zmiany (wykrył zmiany lokalne) i zaktualizował widok.
Możliwe scenariusze to:
1- Detektor zmian jest odłączony od widoku (patrz odłączanie )
2- Nastąpiła aktualizacja, ale nie było jej w Angular Zone, dlatego Angular o tym nie wie.
Tak jak wtedy, gdy funkcja innej firmy zaktualizowała Twój model i chcesz zaktualizować widok po tym.
someFunctionThatIsRunByAThirdPartyCode(){
yourModel.text = "new text";
}
Ponieważ ten kod znajduje się poza strefą Angular (prawdopodobnie), najprawdopodobniej musisz upewnić się, że wykryłeś zmiany i zaktualizowałeś widok, w ten sposób:
myFunction(){
someFunctionThatIsRunByAThirdPartyCode();
// Let's detect the changes that above function made to the model which Angular is not aware of.
this.cd.detectChanges();
}
UWAGA :
Istnieją inne sposoby, aby powyższe zadziałało, innymi słowy, istnieją inne sposoby wprowadzenia tej zmiany w cyklu zmian Angulara.
** Możesz umieścić tę funkcję strony trzeciej w strefie zone.run:
myFunction(){
this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
}
** Możesz zawinąć funkcję wewnątrz setTimeout:
myFunction(){
setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
}
3 - Istnieją również przypadki, w których aktualizujesz model po change detection cycle
zakończeniu, w których w takich przypadkach pojawia się ten przerażający błąd:
„Wyrażenie zmieniło się po sprawdzeniu”;
To generalnie oznacza (z języka Angular2):
Widziałem zmianę w Twoim modelu, która była spowodowana jednym z moich zaakceptowanych sposobów (zdarzenia, żądania XHR, setTimeout i ...), a następnie uruchomiłem wykrywanie zmian, aby zaktualizować widok i skończyłem, ale potem był inny funkcja w twoim kodzie, która ponownie zaktualizowała model i nie chcę ponownie uruchamiać wykrywania zmian, ponieważ nie ma już brudnego sprawdzania, takiego jak AngularJS: D i powinniśmy używać jednokierunkowego przepływu danych!
Na pewno napotkasz ten błąd: P.
Kilka sposobów, aby to naprawić:
1- Właściwy sposób : upewnij się, że aktualizacja znajduje się w cyklu wykrywania zmian (aktualizacje Angular2 to jednokierunkowy przepływ, który ma miejsce raz, nie aktualizuj później modelu i przenieś swój kod w lepsze miejsce / czas).
2- Leniwy sposób : po tej aktualizacji uruchom funkcję detectionChanges (), aby angular2 był szczęśliwy, zdecydowanie nie jest to najlepszy sposób, ale jeśli zapytałeś, jakie są możliwe scenariusze, to jest jeden z nich.
W ten sposób mówisz: Szczerze wiem, że uruchomiłeś wykrywanie zmian, ale chcę, abyś zrobił to ponownie, ponieważ musiałem aktualizować coś w locie po zakończeniu sprawdzania.
3- Umieść kod wewnątrz a setTimeout
, ponieważ setTimeout
jest załatany przez strefę i będzie działać detectChanges
po zakończeniu.
Z dokumentów
markForCheck() : void
Zaznacza wszystkie elementy nadrzędne ChangeDetectionStrategy jako do sprawdzenia.
Jest to głównie potrzebne, gdy ChangeDetectionStrategy twojego komponentu jest OnPush .
Sam OnPush oznacza, że uruchamiaj wykrywanie zmian tylko wtedy, gdy wydarzy się którykolwiek z poniższych:
1- Jedno z @inputs komponentu zostało całkowicie zastąpione nową wartością lub po prostu mówiąc, jeśli odniesienie do właściwości @Input uległo całkowitej zmianie.
Więc jeśli ChangeDetectionStrategy twojego komponentu jest OnPush i masz:
var obj = {
name:'Milad'
};
A potem aktualizujesz / mutujesz to tak:
obj.name = "a new name";
To nie będzie aktualizować obj odniesienia, stąd wykrywania zmian nie zamierzam biegać, więc widok nie jest odzwierciedlając aktualizacji / mutacji.
W takim przypadku musisz ręcznie powiedzieć Angularowi, aby sprawdził i zaktualizował widok (markForCheck);
Więc jeśli zrobiłeś to:
obj.name = "a new name";
Musisz to zrobić:
this.cd.markForCheck();
Raczej poniżej spowodowałoby uruchomienie wykrywania zmian:
obj = {
name:"a new name"
};
Który całkowicie zastąpił poprzedni obiekt nowym {}
;
2- Zdarzenie zostało uruchomione, np. Kliknięcie lub coś podobnego albo którykolwiek z komponentów podrzędnych wyemitował zdarzenie.
Wydarzenia takie jak:
- Kliknij
- Keyup
- Wydarzenia subskrypcyjne
- itp.
Krótko mówiąc:
Użyj, detectChanges()
gdy zaktualizowałeś model po uruchomieniu przez angular wykrywania zmian lub jeśli aktualizacja w ogóle nie była w świecie kątowym.
Użyj, markForCheck()
jeśli używasz OnPush i pomijasz ChangeDetectionStrategy
przez mutację niektórych danych lub zaktualizowałeś model wewnątrz setTimeout ;