Wiem o tym Watchers
i Observers
są obliczane, gdy tylko coś się $scope
zmieni w AngularJS. Ale nie mogłem zrozumieć, jaka dokładnie jest różnica między nimi.
Moje początkowe zrozumienie polega na tym, że Observers
są obliczane dla wyrażeń kątowych, które są warunkami po stronie HTML, gdzie są Watchers
wykonywane, gdy $scope.$watch()
funkcja jest wykonywana. Czy właściwie myślę?
javascript
angularjs
Abilash
źródło
źródło
Odpowiedzi:
$ observ () jest metodą naobiekcie Attributes i jako taka może być używana tylko do obserwowania / obserwowania zmiany wartości atrybutu DOM. Jest używany / nazywany tylko wewnątrz dyrektyw. Użyj $ observ, gdy musisz obserwować / obserwować atrybut DOM zawierający interpolację (tj. {{}}).
Na przykład
attr1="Name: {{name}}"
, a następnie w dyrektywie:attrs.$observe('attr1', ...)
.(Jeśli spróbujesz,
scope.$watch(attrs.attr1, ...)
to nie zadziała z powodu {{}} s - dostanieszundefined
.) Użyj $ watch do wszystkiego innego.$ watch () jest bardziej skomplikowane. Może obserwować / oglądać „wyrażenie”, gdzie wyrażenie może być funkcją lub łańcuchem. Jeśli wyrażenie jest łańcuchem, jest ono $ parsowane 'd (tzn. Oceniane jako wyrażenie kątowe ) na funkcję. (Ta funkcja jest nazywana każdym cyklem podsumowania). Wyrażenie ciągu nie może zawierać {{}}. $ watch jest metodą naobiekcie Scope , więc można jej używać / wywoływać wszędzie tam, gdzie masz dostęp do obiektu zakresu, stąd
Ponieważ łańcuchy są oceniane jako wyrażenia kątowe, $ watch jest często używany, gdy chcesz obserwować / oglądać właściwość model / scope. Np.
attr1="myModel.some_prop"
W funkcji kontrolera lub łącza:scope.$watch('myModel.some_prop', ...)
lubscope.$watch(attrs.attr1, ...)
(lubscope.$watch(attrs['attr1'], ...)
).(Jeśli spróbujesz
attrs.$observe('attr1')
, otrzymasz ciągmyModel.some_prop
, który prawdopodobnie nie jest tym, czego chcesz.)Jak omówiono w komentarzach do odpowiedzi @ PrimosK, wszystkie $ obserwacje i $ zegarki są sprawdzane w każdym cyklu podsumowania .
Dyrektywy o zakresach izolowanych są bardziej skomplikowane. Jeśli używana jest składnia „@”, możesz obserwować lub obserwować atrybut DOM zawierający interpolację (tj. {{}}). (Powodem, dla którego działa z $ watch, jest to, że składnia „@” wykonuje dla nas interpolację , dlatego $ watch widzi ciąg bez znaków {{}}.) Aby ułatwić zapamiętanie, kiedy użyć, sugeruję użycie Obserwuj również w tym przypadku.
Aby pomóc to wszystko przetestować, napisałem Plunkera, który definiuje dwie dyrektywy. Jeden (
d1
) nie tworzy nowego zakresu, drugi (d2
) tworzy zakres izolowany. Każda dyrektywa ma te same sześć atrybutów. Każdy atrybut jest zarówno obserwowany, jak i obserwowany.Przejrzyj dziennik konsoli, aby zobaczyć różnice między $ observ i $ watch w funkcji łączenia. Następnie kliknij link i sprawdź, które $ obserwacje i $ zegarki są wywoływane przez zmiany właściwości wprowadzone przez moduł obsługi kliknięć.
Zauważ, że po uruchomieniu funkcji link wszelkie atrybuty zawierające {{}} nie są jeszcze oceniane (więc jeśli spróbujesz zbadać atrybuty, otrzymasz
undefined
). Jedynym sposobem, aby zobaczyć interpolowane wartości, jest użycie $ observ (lub $ watch, jeśli używasz zakresu izolowanego z '@'). Dlatego uzyskanie wartości tych atrybutów jest operacją asynchroniczną . (I dlatego potrzebujemy funkcji $ observ i $ watch.)Czasami nie potrzebujesz obserwować ani oglądać. Na przykład, jeśli atrybut zawiera liczbę lub wartość logiczną (nie łańcuch), tylko jeden raz ocenić to:
attr1="22"
, a potem, powiedzmy, w swojej funkcji łączącej:var count = scope.$eval(attrs.attr1)
. Jeśli jest to ciąg stały -attr1="my string"
- po prostu użyjattrs.attr1
w swojej dyrektywie (nie potrzebujesz $ eval ()).Zobacz także post grupy google Vojty na temat wyrażeń $ watch.
źródło
ng-src/ng-href
używać ?attr.$observe
scope.$watch
@
składni. Uważam, że nie ma różnicy w wydajności (ale nie spojrzałem na rzeczywisty kod źródłowy).Jeśli dobrze rozumiem twoje pytanie, pytasz, jaka jest różnica, jeśli zarejestrujesz oddzwonienie do słuchacza
$watch
lub jeśli to zrobisz$observe
.Oddzwanianie zarejestrowane za pomocą
$watch
jest uruchamiane, gdy$digest
jest wykonywane.Zarejestrowane wywołanie zwrotne
$observe
jest wywoływane, gdy zmiany wartości atrybutów zawierających interpolację (npattr="{{notJetInterpolated}}"
.).Wewnątrz dyrektywy możesz używać obu z nich w bardzo podobny sposób:
lub
źródło
$digest
fazie, można bezpiecznie założyć, że$observe
wywołanie zwrotne zostanie wywołane$digest
. I$watch
zwrotna zostanie również wezwany$digest
ale ilekroć wartość ulega zmianie. Myślę, że wykonują dokładnie to samo zadanie: „obserwuj wyrażenie, oddzwoń zmiany wartości”. Różnica słów kluczowych to prawdopodobnie tylko cukier składniowy, aby nie mylić dewelopera.Myślę, że to dość oczywiste:
Pamiętaj : obie funkcje mają dwa argumenty,
function (oldValue, newValue)
Zrobiłem plunker, więc możesz naprawdę zrozumieć oba sposoby ich wykorzystania. Użyłem analogii Chameleon, aby ułatwić sobie wyobrażenie.
źródło
Dlaczego $ observ różni się od $ watch?
Funkcja watchExpression jest oceniana i porównywana z poprzednią wartością w każdym cyklu digest (), jeśli nastąpi zmiana wartości watchExpression, wywoływana jest funkcja watch.
$ observ jest specyficzny dla obserwowania wartości interpolowanych. Jeśli wartość atrybutu dyrektywy jest interpolowana, np.
dir-attr="{{ scopeVar }}"
Funkcja obserwacyjna będzie wywoływana tylko wtedy, gdy ustawiona jest wartość interpolowana (a zatem, gdy $ digest określił już aktualizacje, należy dokonać aktualizacji). Zasadniczo istnieje już obserwator interpolacji, a funkcja obserwowania $ piggyback poza tym.Zobacz $ observ & $ set w pliku compile.js
źródło