$ applique () et $ digest () sont deux concepts de base dans AngularJS, mais parfois ils sont déroutants. Afin de comprendre comment fonctionne AngularJS, vous devez d'abord comprendre comment $ appliquez () et $ digest () fonctionnent. Cet article vise à expliquer ce que sont $ appliquer () et $ digest () et comment ils sont appliqués dans le codage quotidien.
1. Explorer $ appliquer () et $ digest ()
1.1. Comprendre la liaison des données bidirectionnelle et $ watch ();
AngularJS fournit une fonctionnalité très cool appelée liaison de données bidirectionnelle, ce qui simplifie considérablement la façon dont nous écrivons notre code. La liaison des données signifie que lorsque des données dans la vue changent, la modification sera automatiquement renvoyée aux données de portée, ce qui signifie que le modèle de portée sera automatiquement mis à jour. De même, lorsque le modèle de portée change, les données de la vue sont mises à jour vers la dernière valeur. Alors, comment fait AngularJS? Lorsque vous écrivez une expression comme {{AMODEL}}, AngularJS définira un observateur pour vous sur le modèle Scope, qui est utilisé pour mettre à jour la vue lorsque les données changent. L'observateur ici est le même que l'observateur que vous définissez dans AngularJS:
$ scope. $ watch ('AMODEL', fonction (newValue, OldValue) {// Mettez à jour le DOM avec newValue});Le deuxième paramètre passé dans $ watch () est une fonction de rappel, qui sera appelée lorsque la valeur d'AMODEL change. Lorsque AMODEL change, il n'est pas difficile de comprendre que cette fonction de rappel sera appelée pour mettre à jour la vue, mais il y a toujours un problème très important! Comment AngularJS sait-il quand appeler cette fonction de rappel? En d'autres termes, comment AngularJS a-t-il appelé la fonction de rappel correspondante lorsqu'il sait qu'Amodel a changé? Exécutera-t-il une fonction périodiquement pour vérifier si les données du modèle de portée ont changé? Eh bien, c'est là que la boucle $ digest entre en jeu.
Dans la boucle $ digest, les observateurs seront licenciés. Lorsqu'un observateur est déclenché, AngularJS détectera le modèle de portée. S'il change, la fonction de rappel associée à l'observateur sera appelée. Donc, la question suivante est de savoir quand la boucle $ digest commence-t-elle de diverses manières?
Après avoir appelé $ scope. $ Digest (), la boucle $ digest commence. Supposons que vous modifiez une portée dans la fonction du gestionnaire correspondant à une directive NG-Click, AngularJS déclenchera automatiquement une boucle $ digest en appelant $ digest (). Lorsque la boucle $ digest commence, elle déclenche chaque observateur. Ces observateurs vérifieront si la valeur actuelle du modèle dans la portée est différente de la valeur du modèle calculée la dernière fois. S'il est différent, la fonction de rappel correspondante sera exécutée. Le résultat de l'appel de cette fonction est que le contenu de l'expression dans la vue (note du traducteur: tel que {{AMODEL}}) sera mis à jour. En plus de la directive NG-Click, il existe d'autres directives et services intégrés pour vous permettre de modifier des modèles (tels que Ng-Model, $ timeout, etc.) et déclencher automatiquement une boucle $ digest.
Jusqu'à présent, ce n'est pas mal! Cependant, il y a un petit problème. Dans l'exemple ci-dessus, AngularJs n'appelle pas $ digest () directement, mais appelle $ scope. $ Applaiter (), qui appelle $ rootscope. $ Digest (). Par conséquent, une boucle $ digest démarre à $ Rootscope, qui accédera ensuite à tous les observateurs de portée des enfants.
Remarque: $ scope. $ Applique () appellera automatiquement $ rootscope. $ Digest ().
La méthode $ applique () a deux formulaires:
Le premier acceptera une fonction en tant que paramètre, exécutera la fonction et déclenchera une boucle $ digest.
Le deuxième type n'acceptera aucun paramètre et déclenchera simplement une boucle $ digest. Nous verrons tout de suite pourquoi le premier formulaire est meilleur.
1.2. Quand appeler manuellement la méthode $ applique ()?
Si AngularJS enveloppe toujours notre code dans une fonction et passez dans $ applique () pour démarrer une boucle de digestion $, quand devons-nous appeler manuellement la méthode $ applique ()? En fait, AngularJS a une exigence très claire à cela, qu'il n'est responsable que de répondre automatiquement aux modifications qui se produisent dans le contexte angularjs (c'est-à-dire des modifications des modèles qui se produisent dans la méthode $ applicable ()). C'est ainsi que la directive intégrée d'AngularJS le fait, donc tout changement de modèle sera reflété dans la vue. Cependant, si vous modifiez le modèle n'importe où en dehors du contexte AngularJS, vous devez informer manuellement AngularJS en appelant $ applique (). C'est comme dire à AngularJS que vous avez modifié certains modèles et espérez qu'AngularJS peut vous aider à déclencher des observateurs à répondre correctement.
Par exemple, si vous utilisez setTimeout () dans JavaScript pour mettre à jour un modèle de portée, AngularJS n'a aucun moyen de savoir ce que vous avez changé. Dans ce cas, il est de votre responsabilité d'appeler $ appliquer () et de déclencher une boucle $ digest en l'appelant. De même, si vous avez une directive pour définir un écouteur d'événements DOM et modifier certains modèles dans cet écouteur, vous devez également appeler $ appliquer () manuellement pour vous assurer que les modifications seront correctement reflétées dans la vue.
Regardons un exemple. Rejoignez-vous une page qui une fois la page chargée, vous souhaitez afficher un message après deux secondes. Votre implémentation peut ressembler à ceci:
HTML:
<body ng-app = "myApp"> <div ng-contrôleur = "MessageController"> Message retardé: {{message}} </div> </ body>Javascript:
/ * Ce qui se passe sans un $ applicable () * / angular.module ('myApp', []). Controller ('MessageController', function ($ scope) {$ scope.getMessage = 'fund () {Settimeout (function () {$ scope.message =' fetchred après 3 secondes '; console.log (' Message: '+ $ scope. } $ scope.getMessage ();});En exécutant cet exemple, vous verrez qu'après deux secondes, la console affiche le modèle mis à jour, cependant, la vue n'est pas mise à jour. Peut-être que vous connaissez déjà la raison, c'est-à-dire que nous avons oublié d'appeler la méthode $ applique (). Par conséquent, nous devons modifier getMessage () comme suit:
/ * Ce qui se passe avec $ applique * / angular.module ('myApp', []). Controller ('MessageController', function ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope. $ scope.Message);});}, 2000);Si vous exécutez l'exemple ci-dessus, vous verrez que la vue sera également mise à jour après deux secondes. Le seul changement est que notre code est désormais enveloppé dans $ scope. $ Applique (), qui déclenchera automatiquement $ rootscope. $ Digest (), afin que les observateurs soient déclenchés pour mettre à jour la vue.
Remarque: Soit dit en passant, vous devez utiliser $ Timeout Service au lieu de setTimeout (), car le premier appellera $ appliquer () pour vous, vous n'avez donc pas besoin de l'appeler manuellement.
Notez également que dans le code ci-dessus, vous pouvez également appeler manuellement $ appliquer () sans paramètres après avoir modifié le modèle, tout comme les suivants:
$ scope.getMessage = function () {setTimeout (function () {$ scope.message = 'obtenu après deux secondes'; console.log ('message:' + $ scope.message); $ scope. $ applique (); // ceci déclenche un $ digest}, 2000); };Le code ci-dessus utilise la deuxième forme de $ applique (), c'est-à-dire la forme sans paramètres. Il est important de se rappeler que vous devez toujours utiliser la méthode $ applique () qui prend une fonction en tant que paramètre. En effet, lorsque vous transmettez une fonction dans $ applique (), la fonction sera enveloppée dans un bloc d'essai ... Catch, donc une fois qu'une exception se produira, l'exception sera traitée par le service $ exceptionhandler.
La situation d'utilisation de $ applique () est la suivante:
• Vous pouvez généralement appeler $ appliquer () en fonction de toute directive fournie par Angular qui peut être utilisée dans la vue. Toutes les directives Ng- [événement] (telles que Ng-Click, Ng-KeyPress) appellent $ applique ().
• De plus, vous pouvez également compter sur une série de services intégrés angulaires pour appeler $ digest (). Par exemple, le service $ HTTP appellera $ application () une fois la demande XHR terminée et la valeur de retour de mise à jour est déclenchée.
• Chaque fois que nous gérons manuellement les événements, utilisons des frameworks tiers (tels que jQuery, Facebook API) ou des appels setTimeOut (), nous pouvons utiliser la fonction $ applique () pour faire de Angular Return une boucle de digest.
Appel setTimeout ():
<! Doctype html> <html ng-app = "myApp"> <éadf> <ititle> $ scope. $ Application () usage </title> <meta charset = "utf-8"> <script src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </ script> </ head> <body> <div id = "div1" ng-Controller = "Mytex Value = "jQuery-Event"> </ Input> </ Div> </ Body> </ Html> <Script Type = "Text / JavaScript"> var Mymodule = Angular.Module ('MyApp', []); MyModule.Controller ("MyText", fonction ($ Scope) {$ scope.text = "Place"; setTimeout (function () {$ scope.text = "valeur définie après le temps out"; $ SCOPE. $ Apply (); // Dirty Value Detection doit être effectué manuellement, sinon les données ne peuvent pas être rafraîchies à l'interface}, 1000);}); </cript>Utilisez des frameworks tiers (comme JQuery, API Facebook):
<! Doctype html> <html ng-app = "myApp"> <éad> <Title> $ scope. $ Applique () usage </ title> <meta charset = "utf-8"> <script src = "https://cdn.jsdelivr.net/jquery/3.1.0/jquery.min.js"> </ script> src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </ script> <body> <div id = "div1" ng-controller = "mytex </div> </ body> </ html> <script type = "text / javascript"> var mymodule = angular.module ('myApp', []); MyModule.Controller ("MyText", fonction ($ scope) {$ scope.text = "place";}); $ (function () {$ ("# btn"). cliquez (function () {var $ scope = $ ("# btn"). scope (); $ scope.text = "valeur définie dans jQuery"; $ scope. $ applique ();});}) </ script>1.3. Combien de fois la boucle $ digest fonctionnera-t-elle?
Lorsqu'une boucle $ digest est en cours d'exécution, les observateurs seront exécutés pour vérifier si les modèles de portée ont changé. Si un changement se produit, la fonction d'écoute correspondante sera exécutée. Cela implique un problème important. Que se passe-t-il si la fonction de l'auditeur elle-même modifie un modèle de portée? Comment AngularJS gérera-t-il cette situation?
La réponse est que la boucle $ digest ne fonctionnera qu'une seule fois. Une fois la boucle actuelle, il exécutera une autre boucle pour vérifier si les modèles ont changé. Il s'agit d'une vérification sale, qui est utilisée pour gérer les modifications du modèle qui peuvent se produire lorsque la fonction de l'écoute est exécutée. Par conséquent, la boucle $ digest continuera de fonctionner jusqu'à ce que le modèle ne change plus, ou la boucle $ digest atteint 10 fois. Par conséquent, essayez de ne pas modifier autant que possible le modèle dans la fonction de l'écoute.
Remarque: la boucle $ digest fonctionnera également au moins deux fois, même si aucun modèle n'est modifié dans la fonction d'écoute. Comme discuté ci-dessus, il se déroulera à nouveau pour s'assurer que les modèles ne changent pas.
Conclusion
La chose la plus importante à retenir est de savoir si AngularJS peut détecter vos modifications au modèle. S'il ne peut pas être détecté, vous devez appeler $ appliquer () manuellement.
Si vous avez des questions, veuillez me laisser un message et l'éditeur répondra à tout le monde à temps. Merci beaucoup pour votre soutien au site Web Wulin.com!