Je sais que les deux Watchers
et Observers
sont calculés dès que quelque chose $scope
change dans AngularJS. Mais je ne pouvais pas comprendre quelle est exactement la différence entre les deux.
Ma compréhension initiale est que Observers
sont calculées pour les expressions angulaires qui sont des conditions du côté HTML où elles sont Watchers
exécutées lorsque la $scope.$watch()
fonction est exécutée. Suis-je en train de penser correctement?
javascript
angularjs
Abilash
la source
la source
Réponses:
$ observe () est une méthode sur l'objet Attributs , et en tant que telle, elle ne peut être utilisée que pour observer / surveiller le changement de valeur d'un attribut DOM. Il est uniquement utilisé / appelé directives internes. Utilisez $ observe lorsque vous devez observer / surveiller un attribut DOM qui contient une interpolation (c'est-à-dire {{}}).
Par exemple,
attr1="Name: {{name}}"
puis dans une directive:attrs.$observe('attr1', ...)
.(Si vous essayez,
scope.$watch(attrs.attr1, ...)
cela ne fonctionnera pas à cause des {{}} - vous obtiendrezundefined
.) Utilisez $ watch pour tout le reste.$ watch () est plus compliqué. Il peut observer / regarder une "expression", où l'expression peut être soit une fonction, soit une chaîne. Si l'expression est une chaîne, elle est $ parse 'd (c'est-à-dire évaluée comme une expression angulaire ) dans une fonction. (C'est cette fonction qui est appelée à chaque cycle de résumé.) L'expression de chaîne ne peut pas contenir de {{}}. $ watch est une méthode sur l'objet Scope , elle peut donc être utilisée / appelée partout où vous avez accès à un objet Scope , donc dans
Étant donné que les chaînes sont évaluées en tant qu'expressions angulaires, $ watch est souvent utilisé lorsque vous souhaitez observer / surveiller une propriété de modèle / portée. Par exemple,,
attr1="myModel.some_prop"
puis dans une fonction de contrôleur ou de liaison:scope.$watch('myModel.some_prop', ...)
ouscope.$watch(attrs.attr1, ...)
(ouscope.$watch(attrs['attr1'], ...)
).(Si vous essayez,
attrs.$observe('attr1')
vous obtiendrez la chaînemyModel.some_prop
, ce qui n'est probablement pas ce que vous voulez.)Comme discuté dans les commentaires sur la réponse de @ PrimosK, tous les $ observes et $ watch sont vérifiés à chaque cycle de résumé .
Les directives avec des étendues isolées sont plus compliquées. Si la syntaxe '@' est utilisée, vous pouvez $ observer ou $ regarder un attribut DOM qui contient une interpolation (c'est-à-dire {{}}). (La raison pour laquelle il fonctionne avec $ watch est parce que la syntaxe '@' fait l' interpolation pour nous, donc $ watch voit une chaîne sans {{}}.) Pour qu'il soit plus facile de se rappeler laquelle utiliser quand, je suggère d'utiliser Observer également pour ce cas.
Pour aider à tester tout cela, j'ai écrit un Plunker qui définit deux directives. Un (
d1
) ne crée pas de nouvelle étendue, l'autre (d2
) crée une étendue isolée. Chaque directive a les six mêmes attributs. Chaque attribut est à la fois $ observé et $ surveillé.Regardez le journal de la console pour voir les différences entre $ observ et $ watch dans la fonction de liaison. Cliquez ensuite sur le lien et voyez quels $ observes et $ watch sont déclenchés par les changements de propriétés effectués par le gestionnaire de clic.
Notez que lorsque la fonction de lien s'exécute, tous les attributs qui contiennent des {{}} ne sont pas encore évalués (donc si vous essayez d'examiner les attributs, vous obtiendrez
undefined
). La seule façon de voir les valeurs interpolées est d'utiliser $ observ (ou $ watch si vous utilisez une portée isolée avec '@'). Par conséquent, l'obtention des valeurs de ces attributs est une opération asynchrone . (Et c'est pourquoi nous avons besoin des fonctions $ observe et $ montre.)Parfois, vous n'avez pas besoin de $ observe ou $ watch. Par exemple, si votre attribut contient un numéro ou un booléen (pas une chaîne), juste une fois évaluer:
attr1="22"
, puis, disons, votre fonction de liaison:var count = scope.$eval(attrs.attr1)
. Si c'est juste une chaîne constante -attr1="my string"
- alors utilisez simplementattrs.attr1
dans votre directive (pas besoin de $ eval ()).Voir aussi le message du groupe Google de Vojta sur les expressions $ watch.
la source
ng-src/ng-href
utiliserattr.$observe
au lieu de celascope.$watch
?@
syntaxe. Je crois qu'il n'y a pas de différence de performances (mais je n'ai pas regardé le code source réel).Si je comprends bien votre question, vous demandez quelle est la différence si vous enregistrez le rappel de l'auditeur avec
$watch
ou si vous le faites avec$observe
.Le rappel enregistré avec
$watch
est déclenché lors de$digest
son exécution.Le rappel enregistré avec
$observe
est appelé lorsque la valeur change des attributs qui contiennent une interpolation (par exempleattr="{{notJetInterpolated}}"
).Dans la directive Inside, vous pouvez utiliser les deux de manière très similaire:
ou
la source
$digest
phase, il est sûr de supposer que le$observe
rappel sera appelé$digest
. Et le$watch
rappel sera également appelé$digest
mais chaque fois que la valeur est modifiée. Je pense qu'ils font exactement le même travail: "regardez l'expression, rappelez la valeur change". La différence entre les mots clés est peut-être simplement du sucre syntaxique pour ne pas dérouter le développeur.Je pense que c'est assez évident:
Gardez à l'esprit : à la fois la fonction a deux arguments,
function (oldValue, newValue)
J'ai fait un plunker, donc vous pouvez réellement comprendre à la fois leur utilisation. J'ai utilisé l'analogie Chameleon pour le rendre plus facile à imaginer.
la source
Pourquoi $ observe est-il différent de $ watch?
Le watchExpression est évalué et comparé à la valeur précédente à chaque cycle digest (), s'il y a un changement dans la valeur watchExpression, la fonction watch est appelée.
$ observe est spécifique à la recherche de valeurs interpolées. Si la valeur d'attribut d'une directive est interpolée, par exemple
dir-attr="{{ scopeVar }}"
, la fonction observe ne sera appelée que lorsque la valeur interpolée est définie (et donc lorsque $ digest a déjà déterminé des mises à jour doivent être effectuées). Fondamentalement, il existe déjà un observateur pour l'interpolation, et la fonction $ observe se superpose à cela.Voir $ observe & $ set dans compile.js
la source