Comment utiliser $ scope. $ Watch et $ scope. $ Dans AngularJS?

Je ne comprends pas comment utiliser $scope.$watch et $scope.$apply . La documentation officielle n’est pas utile

Ce que je ne comprends pas spécifiquement:

  • Sont-ils connectés au DOM?
  • Comment puis-je mettre à jour les modifications DOM sur le modèle?
  • Quel est le sharepoint connexion entre eux?

J’ai essayé ce tutoriel , mais cela prend la compréhension de $watch et de $apply for acquises.

Qu’est-ce que $apply et $watch font et comment les utiliser correctement?

Vous devez savoir comment AngularJS fonctionne pour le comprendre.

Cycle de digestion et étendue $

AngularJS définit avant tout un concept de cycle dit de digestion . Ce cycle peut être considéré comme une boucle, pendant laquelle AngularJS vérifie s’il y a des modifications à toutes les variables surveillées par tous les $scope s. Donc, si $scope.myVar défini dans votre contrôleur et que cette variable a été marquée pour être surveillée , vous $scope.myVar implicitement à AngularJS de surveiller les modifications sur myVar à chaque itération de la boucle.

Une question de suivi naturelle serait: Est-ce que tout ce qui est attaché à $scope est surveillé? Heureusement non. Si vous surveilliez les modifications apscopes à chaque object de votre $scope , alors une boucle de résumé prendrait du temps à être évaluée et vous rencontreriez rapidement des problèmes de performances. C’est pourquoi l’équipe d’AngularJS nous a donné deux façons de déclarer une variable $scope comme étant surveillée (voir ci-dessous).

$ watch aide à écouter les changements de $ scope

Il existe deux manières de déclarer une variable $scope comme étant surveillée.

  1. En l’utilisant dans votre modèle via l’expression {{myVar}}
  2. En l’ajoutant manuellement via le service $watch

Ad 1) Ceci est le scénario le plus courant et je suis sûr que vous l’avez déjà vu, mais vous ne saviez pas que cela a créé une montre en arrière-plan. Oui, c’était le cas! L’utilisation de directives AngularJS (telles que ng-repeat ) peut également créer des montres implicites.

Ad 2) Voici comment vous créez vos propres montres . $watch service $watch vous aide à exécuter du code lorsque certaines valeurs attachées à la $scope ont été modifiées. Il est rarement utilisé, mais est parfois utile. Par exemple, si vous souhaitez exécuter du code chaque fois que «myVar» change, vous pouvez procéder comme suit:

 function MyController($scope) { $scope.myVar = 1; $scope.$watch('myVar', function() { alert('hey, myVar has changed!'); }); $scope.buttonClicked = function() { $scope.myVar = 2; // This will sortinggger $watch expression to kick in }; } 

$ apply permet d’intégrer les changements au cycle de digestion

Vous pouvez penser à la fonction $apply comme à un mécanisme d’intégration . Vous voyez, chaque fois que vous modifiez directement une variable surveillée attachée à l’ object $scope , AngularJS saura que le changement est arrivé. C’est parce qu’AngularJS savait déjà surveiller ces changements. Donc, si cela se produit dans le code géré par le framework, le cycle de digestion se poursuivra.

Cependant, vous voulez parfois changer une valeur en dehors du monde AngularJS et voir les modifications se propager normalement. Considérez ceci – vous avez une valeur $scope.myVar qui sera modifiée dans le $.ajax() jQuery. Cela se produira à un moment donné dans le futur. AngularJS a hâte que cela se produise, car il n’a pas été demandé d’attendre sur jQuery.

Pour y remédier, $apply a été introduit. Il vous permet de démarrer le cycle de digestion explicitement. Cependant, vous ne devriez l’utiliser que pour migrer certaines données vers AngularJS (intégration avec d’autres frameworks), mais n’utilisez jamais cette méthode associée au code AngularJS standard, car AngularJS générera alors une erreur.

Comment tout cela est-il lié au DOM?

Eh bien, vous devriez vraiment suivre le tutoriel à nouveau, maintenant que vous savez tout cela. Le cycle de digestion s’assurera que l’interface utilisateur et le code JavaScript restnt synchronisés, en évaluant chaque observateur connecté à tous les $scope s tant que rien ne change. Si plus aucune modification ne se produit dans la boucle de résumé, elle est considérée comme terminée.

Vous pouvez attacher des objects à l’object $scope soit explicitement dans le contrôleur, soit en les déclarant sous la forme {{expression}} directement dans la vue.

J’espère que cela aide à clarifier certaines connaissances de base sur tout cela.

Lectures complémentaires:

  • Make Your Own AngularJS, Partie 1: Scopes Et Digest

Dans AngularJS, nous mettons à jour nos modèles et nos vues / modèles mettent à jour le DOM “automatiquement” (via des directives intégrées ou personnalisées).

$ apply et $ watch, les deux étant des méthodes Scope, ne sont pas liés au DOM.

La page Concepts (section “Runtime”) contient une assez bonne explication de la boucle $ digest, de $ apply, de la queue $ evalAsync et de la liste $ watch. Voici la photo qui accompagne le texte:

$ digest loop

Quel que soit le code ayant access à une étendue – normalement, les contrôleurs et les directives (leurs fonctions de liaison et / ou leurs contrôleurs) – peuvent configurer une ” watchExpression ” que AngularJS évaluera par rapport à cette scope. Cette évaluation a lieu chaque fois qu’AngularJS entre dans sa boucle $ digest (en particulier la boucle “$ watch list”). Vous pouvez voir les propriétés de scope individuelles, vous pouvez définir une fonction pour regarder deux propriétés ensemble, vous pouvez regarder la longueur d’un tableau, etc.

Quand les choses se passent “dans AngularJS” – par exemple, vous tapez dans une zone de texte avec une liaison bidirectionnelle AngularJS activée (c.-à-d. Utilise ng-model), un callback $ http se déclenche, etc. sont dans le rectangle “AngularJS” dans la figure ci-dessus. Toutes les expressions de watchExpress seront évaluées (éventuellement plus d’une fois – jusqu’à ce qu’aucune autre modification ne soit détectée).

Lorsque les choses se passent “hors AngularJS” – par exemple, vous avez utilisé bind () dans une directive et que cet événement se déclenche, entraînant l’appel de votre rappel ou certains rappels enregistrés jQuery – nous sums toujours dans le rectangle “Native”. Si le code de rappel modifie tout ce que $ watch surveille, appelez $ apply pour entrer dans le rectangle AngularJS, ce qui provoque l’exécution de la boucle $ digest et AngularJS remarquera donc le changement et effectuera sa magie.

Ce blog a été couvert tout ce qui crée des exemples et des explications compréhensibles.

Les fonctions $scope $watch(), $digest() et $apply() AngularJS $scope font partie des fonctions centrales d’AngularJS. Comprendre $watch() , $digest() et $apply() est essentiel pour comprendre AngularJS.

Lorsque vous créez une liaison de données entre votre sharepoint vue et une variable de l’object $ scope, AngularJS crée une “montre” en interne. Une montre signifie que AngularJS surveille les modifications de la variable sur l’ $scope object . Le framework “regarde” la variable. Les montres sont créées en utilisant la fonction $scope.$watch() que je couvrirai plus tard dans ce texte.

Aux points clés de votre application, AngularJS appelle la fonction $scope.$digest() . Cette fonction parcourt toutes les montres et vérifie si l’une des variables surveillées a été modifiée. Si une variable surveillée a changé, une fonction d’écouteur correspondante est appelée. La fonction d’écoute effectue tout le travail nécessaire, par exemple en modifiant un texte HTML pour refléter la nouvelle valeur de la variable surveillée. Ainsi, la fonction $digest() déclenche la mise à jour de la liaison de données.

La plupart du temps, AngularJS appellera les fonctions $ scope. $ Watch () et $scope.$digest() pour vous, mais dans certaines situations, vous devrez peut-être les appeler vous-même. Par conséquent, il est vraiment bon de savoir comment ils fonctionnent.

La fonction $scope.$apply() est utilisée pour exécuter du code, puis appelle $scope.$digest() pour que toutes les montres soient vérifiées et que les fonctions d’écoute de surveillance correspondantes soient appelées. La fonction $apply() est utile pour intégrer AngularJS à un autre code.

Je vais entrer dans plus de détails sur les fonctions $watch(), $digest() et $apply() dans la suite de ce texte.

$ watch ()

La fonction $scope.watch() crée une montre de certaines variables. Lorsque vous enregistrez une montre, vous passez deux fonctions en tant que parameters à la fonction $watch() :

  • Une fonction de valeur
  • Une fonction d’écoute

Voici un exemple:

 $scope.$watch(function() {}, function() {} ); 

La première fonction est la fonction valeur et la deuxième fonction est la fonction écouteur.

La fonction value doit renvoyer la valeur surveillée. AngularJS peut alors vérifier la valeur renvoyée par rapport à la valeur renvoyée par la fonction watch la dernière fois. De cette façon, AngularJS peut déterminer si la valeur a changé. Voici un exemple:

 $scope.$watch(function(scope) { return scope.data.myVar }, function() {} ); 

Cet exemple de fonction valule renvoie la variable $scope scope.data.myVar . Si la valeur de cette variable change, une valeur différente sera renvoyée et AngularJS appellera la fonction d’écouteur.

Remarquez comment la fonction value prend la scope en paramètre (sans le $ dans le nom). Via ce paramètre, la fonction value peut accéder à $scope et à ses variables. La fonction value peut également regarder les variables globales si vous en avez besoin, mais le plus souvent, vous observerez une variable $scope .

La fonction d’écoute doit faire ce qu’elle doit faire si la valeur a changé. Vous devez peut-être modifier le contenu d’une autre variable ou définir le contenu d’un élément HTML ou quelque chose. Voici un exemple:

 $scope.$watch(function(scope) { return scope.data.myVar }, function(newValue, oldValue) { document.getElementById("").innerHTML = "" + newValue + ""; } ); 

Cet exemple définit le code HTML interne d’un élément HTML sur la nouvelle valeur de la variable, incorporée dans l’élément b, ce qui rend la valeur en gras. Bien sûr, vous auriez pu le faire en utilisant le code {{ data.myVar } , mais ceci n’est qu’un exemple de ce que vous pouvez faire dans la fonction d’écouteur.

$ digest ()

La fonction $scope.$digest() une itération à travers toutes les montres de l’ $scope object et de ses objects child $ scope (le cas échéant). Lorsque $digest() répété sur les montres, il appelle la fonction de valeur pour chaque montre. Si la valeur renvoyée par la fonction value est différente de la valeur renvoyée la dernière fois qu’elle a été appelée, la fonction d’écoute de cette montre est appelée.

La fonction $digest() est appelée chaque fois que AngularJS le juge nécessaire. Par exemple, après l’exécution d’un gestionnaire de clic sur un bouton ou après le retour d’un appel AJAX (après l’exécution de la fonction de rappel done () / fail ()).

Vous pouvez rencontrer certains cas où AngularJS n’appelle pas la fonction $digest() pour vous. Vous détecterez généralement cela en remarquant que les liaisons de données ne mettent pas à jour les valeurs affichées. Dans ce cas, appelez $scope.$digest() et cela devrait fonctionner. Ou, vous pouvez peut-être utiliser $scope.$apply() place, que j’expliquerai dans la section suivante.

$ appliquer ()

La fonction $scope.$apply() prend une fonction comme paramètre qui est exécutée et après cela, $scope.$digest() est appelé en interne. Cela vous permet de vérifier plus facilement que toutes les montres sont vérifiées et que toutes les liaisons de données sont actualisées. Voici un exemple de $apply() :

 $scope.$apply(function() { $scope.data.myVar = "Another value"; }); 

La fonction transmise à la fonction $apply() tant que paramètre changera la valeur de $scope.data.myVar . Lorsque la fonction se ferme, AngularJS appelle la fonction $scope.$digest() afin que toutes les montres soient vérifiées pour les changements dans les valeurs surveillées.

Exemple

Pour illustrer le fonctionnement de $watch() , $digest( ) et $apply() , regardez cet exemple:

 
{{data.time}}

Son exemple lie la variable $scope.data.time à une directive d’interpolation qui fusionne la valeur de la variable dans la page HTML. Cette liaison crée une montre en interne sur la $scope.data.time variable .

L’exemple contient également deux boutons. Le premier bouton est associé à un écouteur ng-click . Lorsque vous cliquez sur ce bouton, la fonction $scope.updateTime() est appelée, puis AngularJS appelle $scope.$digest() pour que les liaisons de données soient mises à jour.

Le second bouton reçoit un écouteur standard d’événement JavaScript attaché à l’intérieur de la fonction de contrôleur. Lorsque le deuxième bouton est cliqué, cette fonction d’écoute est exécutée. Comme vous pouvez le voir, les fonctions d’écoute des deux boutons sont presque identiques, mais lorsque la fonction d’écoute du deuxième bouton est appelée, la liaison de données n’est pas mise à jour. En effet, la $scope.$digest() n’est pas appelée après l’exécution de l’écouteur d’événement du deuxième bouton. Ainsi, si vous cliquez sur le deuxième bouton, l’heure est mise à jour dans la variable $scope.data.time , mais la nouvelle heure n’est jamais affichée.

Pour résoudre ce problème, nous pouvons append un appel $scope.$digest() à la dernière ligne de l’écouteur d’événement du bouton, comme ceci:

 document.getElementById("updateTimeButton") .addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); $scope.$digest(); }); 

Au lieu d’appeler $digest() dans la fonction d’écouteur de bouton, vous pourriez aussi avoir utilisé la fonction $apply() comme ceci:

 document.getElementById("updateTimeButton") .addEventListener('click', function() { $scope.$apply(function() { console.log("update time clicked"); $scope.data.time = new Date(); }); }); 

Remarquez comment la fonction $scope.$apply() est appelée depuis l’écouteur d’événements du bouton et comment la mise à jour de la variable $scope.data.time est effectuée à l’intérieur de la fonction passée en paramètre à la fonction $apply() . Lorsque l’appel de la fonction $apply() se termine, AngularJS appelle $digest() interne afin que toutes les liaisons de données soient mises à jour.

AngularJS étend cette boucle d’événements en créant quelque chose appelé AngularJS context .

$ watch ()

Chaque fois que vous liez quelque chose dans l’interface utilisateur, vous insérez une $watch dans une liste $watch .

 User:  Password:  

Nous avons ici $scope.user , qui est lié à la première entrée, et nous avons $scope.pass , qui est lié au second. En faisant cela, nous ajoutons deux $watch à la liste $watch .

Lorsque notre template est chargé, AKA dans la phase de liaison, le compilateur va chercher chaque directive et crée toutes les $watch es nécessaires.

AngularJS fournit $watch , $watchcollection et $watch(true) . Ci-dessous, un diagramme soigné expliquant en détail les trois points tirés des observateurs .

Entrez la description de l'image ici

 angular.module('MY_APP', []).controller('MyCtrl', MyCtrl) function MyCtrl($scope,$timeout) { $scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}]; $scope.$watch("users", function() { console.log("**** reference checkers $watch ****") }); $scope.$watchCollection("users", function() { console.log("**** Collection checkers $watchCollection ****") }); $scope.$watch("users", function() { console.log("**** equality checkers with $watch(true) ****") }, true); $timeout(function(){ console.log("Triggers All ") $scope.users = []; $scope.$digest(); console.log("Triggers $watchCollection and $watch(true)") $scope.users.push({ name: 'Thalaivar'}); $scope.$digest(); console.log("Triggers $watch(true)") $scope.users[0].name = 'Superstar'; $scope.$digest(); }); } 

http://jsfiddle.net/2Lyn0Lkb/

$digest loop

Lorsque le navigateur reçoit un événement pouvant être géré par le contexte AngularJS, la boucle $digest sera déclenchée. Cette boucle est constituée de deux boucles plus petites. L’un traite la queue $evalAsync et l’autre traite la $watch list . Le $digest va parcourir la liste de $watch que nous avons

 app.controller('MainCtrl', function() { $scope.name = "vinoth"; $scope.changeFoo = function() { $scope.name = "Thalaivar"; } }); {{ name }}  

Ici, nous n’avons qu’une seule $watch car ng-click ne crée aucune montre.

Nous appuyons sur le bouton.

  1. Le navigateur reçoit un événement qui entrera dans le contexte AngularJS
  2. La boucle $digest s’exécutera et demandera à toutes les modifications de $ watch.
  3. Dans la mesure où $watch qui surveillait les modifications de $ scope.name, signale une modification, il forcera une autre boucle $digest .
  4. La nouvelle boucle ne rapporte rien.
  5. Le navigateur récupère le contrôle et met à jour le DOM reflétant la nouvelle valeur de $ scope.name
  6. L’important est que CHAQUE événement entrant dans le contexte AngularJS exécute une boucle $digest . Cela signifie que chaque fois que nous écrivons une lettre dans une entrée, la boucle sera exécutée en vérifiant chaque $watch de cette page.

$ appliquer ()

Si vous appelez $apply lorsqu’un événement est déclenché, il passera par le contexte angular, mais si vous ne l’appelez pas, il s’exécutera en dehors de celui-ci. C’est aussi facile que ça. $apply appellera la boucle $digest() interne et itérera toutes les montres pour s’assurer que le DOM est mis à jour avec la nouvelle valeur mise à jour.

La méthode $apply() déclenchera les observateurs sur toute la chaîne $scope alors que la méthode $digest() ne déclenchera que les observateurs sur la $scope actuelle et ses children . Si aucun des objects $scope les plus élevés n’a besoin de connaître les modifications locales, vous pouvez utiliser $digest() .

Il y a aussi $watchGroup et $watchCollection . Plus précisément, $watchGroup est vraiment utile si vous voulez appeler une fonction pour mettre à jour un object qui possède plusieurs propriétés dans une vue qui n’est pas un object dom, par exemple une autre vue dans canvas, WebGL ou une requête serveur. Ici, le lien de documentation.

J’ai trouvé des vidéos très détaillées couvrant les cycles $watch , $apply , $digest et digest dans:

  • AngularJS – Comprendre Watcher, $ watch, $ watchGroup, $ watchCollection, ng-change

  • AngularJS – Comprendre le cycle de digestion (phase de digestion ou processus de digestion ou boucle de digestion)

  • Didacticiel AngularJS – Comprendre $ apply et $ digest (en profondeur)

Voici quelques diapositives utilisées dans ces vidéos pour expliquer les concepts (au cas où, si les liens ci-dessus sont supprimés / ne fonctionnent pas).

Entrez la description de l'image ici

Dans l’image ci-dessus, “$ scope.c” n’est pas surveillé car il n’est utilisé dans aucune liaison de données (en balisage). Les deux autres ( $scope.a et $scope.b ) seront surveillés.

Entrez la description de l'image ici

A partir de l’image ci-dessus: Basé sur l’événement du navigateur respectif, AngularJS capture l’événement, effectue un cycle de digestion (passe en revue toutes les montres pour les modifications), exécute des fonctions de surveillance et met à jour le DOM. S’il ne s’agit pas d’événements du navigateur, le cycle de résumé peut être déclenché manuellement à l’aide de $apply ou de $digest .

En savoir plus sur $apply et $digest :

Entrez la description de l'image ici

Il suffit de finir de lire TOUT ce qui précède, ennuyeux et endormi (désolé mais c’est vrai). Très technique, en profondeur, détaillé et sec. Pourquoi est-ce que j’écris? Comme AngularJS est massif, de nombreux concepts interconnectés peuvent rendre n’importe qui fou. Je me suis souvent demandé si je ne suis pas assez intelligent pour les comprendre. Non! C’est parce que si peu de gens peuvent expliquer la technologie dans un langage factice sans toutes les terminologies! Okay, laisse moi essayer:

1) Ils sont tous des événements liés aux événements. (J’entends le rire, mais continue à lire)

Si vous ne savez pas ce qu’est la gestion des événements Pensez ensuite à placer un bouton sur la page, connectez-vous avec une fonction à l’aide du “clic”, attendez que les utilisateurs cliquent dessus pour déclencher les actions fonction. Ou pensez à “sortinggger” de SQL Server / Oracle.

2) $ watch est “on-click”.

Ce qui est spécial, c’est que 2 fonctions sont des parameters, la première donne la valeur de l’événement, la seconde prend en compte la valeur …

3) $ digest est le patron qui vérifie sans relâche , bla-bla-bla mais un bon patron.

4) $ apply vous donne le moyen de le faire manuellement , comme un test d’échec (au cas où le clic ne se déclenche pas, vous le forcez à s’exécuter).

Maintenant, rendons cela visuel. Imaginez ceci pour rendre l’idée encore plus facile:

Dans un restaurant,

– WAITERS est censé prendre les commandes des clients, ceci est

 $watch( function(){return orders;}, function(){Kitchen make it;} ); 

– GESTIONNAIRE s’exécutant pour s’assurer que tous les serveurs sont éveillés, réactifs à tout signe de changement de la part des clients. Ceci est $digest()

– Le propriétaire a le pouvoir ultime de conduire tout le monde sur demande, ceci est $apply()