AngularJS: différence entre les méthodes $observer et $ watch

je sais que les deux Watchers et Observers sont calculés dès que quelque chose dans $scope changements dans AngularJS. Mais je ne pouvais pas comprendre quelle était la différence entre les deux.

ma compréhension initiale est que Observers sont calculés pour des expressions angulaires qui sont des conditions du côté HTML où comme Watchers exécuté lorsque $scope.$watch() fonction est exécutée. Suis-je de penser correctement?

368
demandé sur Adam Bubela 2013-02-14 17:39:00

4 réponses

$observez () est une méthode sur l'objet attributs , et en tant que tel, il ne peut être utilisé que pour observer/observer le changement de valeur d'un attribut DOM. Il n'est utilisé/appelé qu'à l'intérieur des directives. Utiliser $observer lorsque vous avez besoin d'observer/regarder un DOM attribut qui contient l'interpolation (i.e., {{}}').

E. G., attr1="Name: {{name}}" , puis dans une directive: attrs.$observe('attr1', ...) .

(Si vous essayez scope.$watch(attrs.attr1, ...) ça ne marchera pas à cause du undefined .) Utiliser $regarder pour tout le reste.

$montre () est plus compliqué. On peut observer/regarder une "expression", où l'expression peut être soit une fonction ou d'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 digérer cycle.) L'expression string ne peut pas contenir de {{}}. $watch est une méthode sur l'objet Scope , donc elle peut être utilisée / appelée partout où vous avez accès à un objet scope, donc dans

  • un contrôleur -- n'importe quel contrôleur -- un contrôleur créé via ng-view, ng-controller, ou un contrôleur de directive
  • une fonction de liaison dans une directive, puisqu'elle a accès à un la portée de l'

parce que les chaînes sont évaluées comme des expressions angulaires, $watch est souvent utilisé quand vous voulez observer/regarder une propriété model/scope. Par exemple, attr1="myModel.some_prop" , puis dans une fonction de contrôleur ou de lien: scope.$watch('myModel.some_prop', ...) ou scope.$watch(attrs.attr1, ...) (ou scope.$watch(attrs['attr1'], ...) ).

(si vous essayez attrs.$observe('attr1') vous obtiendrez la chaîne myModel.some_prop , qui n'est probablement pas ce que vous voulez.)

comme discuté dans les commentaires sur @PrimosK réponse, tous les $ observe et $ montres sont vérifiés chaque cycle digest .

Les Directives

avec une portée d'isolat sont plus compliquées. Si la syntaxe ' @ ' est utilisée, Vous pouvez $observer ou $watch un attribut DOM qui contient l'interpolation (i.e., {{}}'s). (La raison pour laquelle cela fonctionne avec $watch est que la syntaxe '@' fait l '"interpolation 1519590920 pour nous, donc $watch voit une chaîne sans {{}}'s.) To make it plus facile de se rappeler ce qu'il faut utiliser quand, je suggère d'utiliser $observer pour ce cas aussi.

pour aider à tester tout cela, j'ai écrit un Plunker qui définit deux directives. L'une ( d1 ) ne crée pas de nouvelle portée, l'autre ( d2 ) crée une portée d'isolat. Chaque directive possède les mêmes six attributs. Chaque attribut est à la fois $observ'D et $ watch'ed.

<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
        attr5="a_string" attr6="{{1+aNumber}}"></div>

regardez le journal de bord de la console pour voir les différences entre $observer et $regarder dans la fonction de liaison. Puis cliquez sur le lien et voyez qui $observe et $montres sont déclenchées par les changements de propriété effectués par le gestionnaire de clic.

notez que lorsque la fonction link s'exécute, tous les attributs qui contiennent {{}}'s 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 $observer (ou $watch si vous utilisez un champ isolat avec '@'). Par conséquent, obtenir les valeurs de ces attributs est une opération asynchrone . (Et c'est pourquoi nous avons besoin des fonctions $observer et $watch.)

parfois vous n'avez pas besoin de $Observer ou $ watch. Par exemple, si votre attribut contient un nombre ou un booléen (pas une chaîne), il suffit de l'évaluer une fois: attr1="22" , puis dans, disons, votre fonction de lien: var count = scope.$eval(attrs.attr1) . Si c'est juste une chaîne constante – attr1="my string" - alors il suffit d'utiliser attrs.attr1 dans votre la directive (pas besoin de $eval()).

Voir aussi Vojta du groupe google post environ $watch expressions.

597
répondu Mark Rajcok 2014-08-11 10:20:17

si je comprends bien votre question, vous vous demandez quelle est la différence si vous enregistrez le rappel de l'auditeur avec $watch ou si vous le faites avec $observe .

Rappel inscrit avec $watch est déclenché lorsque $digest est exécuté.

Callback enregistré avec $observe sont appelés lorsque la valeur change des attributs qui contiennent l'interpolation (par exemple attr="{{notJetInterpolated}}" ).


À l'intérieur de la directive, vous pouvez utiliser les deux de manière très similaire:

    attrs.$observe('attrYouWatch', function() {
         // body
    });

ou

    scope.$watch(attrs['attrYouWatch'], function() {
         // body
    });
21
répondu PrimosK 2018-04-12 11:46:50

je pense que c'est assez évident :

  • $observer est utilisé dans la fonction de liaison des directives.
  • $montre est utilisé sur scope pour regarder tout changement de ses valeurs.

Keep in mind : les deux fonctions ont deux arguments,

$observe/$watch(value : string, callback : function);
  • valeur : est toujours une référence de chaîne de caractères à l'élément observé (le nom d'une variable du champ d'application ou du nom de l'attribut de la directive à surveiller)
  • callback : la fonction à exécuter de la forme function (oldValue, newValue)

j'ai fait un plunker , de sorte que vous pouvez réellement obtenir une main sur leur utilisation. J'ai utilisé L'analogie du caméléon pour faciliter l'image.

1
répondu vdegenne 2015-05-30 20:46:21

pourquoi $ observer est-il différent de $watch?

l'expression de la montre est évaluée et comparée à la valeur précédente de chaque cycle digest (), s'il y a un changement dans la valeur de l'expression de la montre, la fonction de montre est appelée.

$observer est spécifique à l'observation des valeurs interpolées. Si la valeur d'attribut d'une directive est interpolée, par exemple dir-attr="{{ scopeVar }}" , la fonction observer ne sera appelée que lorsque la valeur interpolée est définie (et donc lorsque $digest a déjà déterminé que des mises à jour doivent être faites). Fondamentalement, il y a déjà un observateur pour l'interpolation et l' $observer fonction se greffe.

Voir $observer & $ compiler.js

0
répondu Niko 2018-04-05 16:59:30