Vous devez être conscient du fonctionnement d'AngularJS afin de le comprendre.
Cycle de résumé et portée $
D'abord et avant tout, AngularJS définit un concept d'un soi-disant cycle de digestion . Ce cycle peut être considéré comme une boucle, au cours de laquelle AngularJS vérifie s'il y a des changements à toutes les variables surveillées par tous les $scope
s. Donc, si vous avez $scope.myVar
défini dans votre contrôleur et que cette variable a été marquée pour être surveillée , vous dites implicitement à AngularJS de surveiller les changements myVar
à chaque itération de la boucle.
Une question de suivi naturelle serait: tout est-il attaché à la $scope
surveillance? Heureusement non. Si vous surveilliez les modifications de chaque objet de votre $scope
, alors rapidement une boucle de résumé prendrait beaucoup de temps à évaluer et vous vous heurteriez rapidement à des problèmes de performances. C'est pourquoi l'équipe AngularJS nous a donné deux façons de déclarer une $scope
variable comme étant surveillée (lire ci-dessous).
$ watch aide à écouter les changements de portée de $
Il existe deux façons de déclarer une $scope
variable comme étant surveillée.
- En l'utilisant dans votre modèle via l'expression
<span>{{myVar}}</span>
- En l'ajoutant manuellement via le
$watch
service
Annonce 1) C'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, bien sûr! L'utilisation de directives AngularJS (telles que ng-repeat
) peut également créer des surveillances implicites.
Annonce 2) Voici comment créer vos propres montres . $watch
Le service vous aide à exécuter du code lorsque certaines valeurs attachées à $scope
ont changé. Il est rarement utilisé, mais est parfois utile. Par exemple, si vous souhaitez exécuter du code à chaque fois que «myVar» change, vous pouvez effectuer les opérations suivantes:
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
$ apply permet d'intégrer les changements au cycle de résumé
Vous pouvez considérer la $apply
fonction comme un mécanisme d'intégration . Vous voyez, chaque fois que vous modifiez directement une variable surveillée attachée à l'$scope
objet, AngularJS saura que le changement s'est produit. En effet, AngularJS savait déjà surveiller ces changements. Donc, si cela se produit dans du code géré par le framework, le cycle de résumé se poursuivra.
Cependant, parfois vous voulez changer une valeur en dehors du monde AngularJS et voir les changements se propager normalement. Considérez ceci - vous avez une $scope.myVar
valeur qui sera modifiée dans le $.ajax()
gestionnaire d' un jQuery . Cela se produira à un moment donné à l'avenir. AngularJS ne peut pas attendre que cela se produise, car il n'a pas été invité à attendre sur jQuery.
Pour y remédier, $apply
a été introduit. Il vous permet de démarrer le cycle de digestion de manière explicite. Cependant, vous ne devez l'utiliser que pour migrer certaines données vers AngularJS (intégration avec d'autres frameworks), mais ne jamais utiliser cette méthode combinée avec du code AngularJS normal, car AngularJS lèvera alors une erreur.
Comment tout cela est-il lié au DOM?
Eh bien, vous devriez vraiment suivre à nouveau le tutoriel, maintenant que vous savez tout cela. Le cycle de résumé s'assurera que l'interface utilisateur et le code JavaScript restent synchronisés, en évaluant chaque observateur attaché à tous les $scope
s tant que rien ne change. Si plus aucun changement ne se produit dans la boucle de résumé, alors il est considéré comme terminé.
Vous pouvez attacher des objets à l' $scope
objet soit explicitement dans le Controller, soit en les déclarant sous {{expression}}
forme directement dans la vue.
J'espère que cela aide à clarifier certaines connaissances de base sur tout cela.
Lectures complémentaires:
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, tous deux étant des méthodes Scope, ne sont pas liés au DOM.
La page Concepts (section "Runtime") a une assez bonne explication de la boucle $ digest, $ apply, la file d'attente $ evalAsync et la liste de surveillance $. Voici l'image qui accompagne le texte:
Quel que soit le code ayant accès à une étendue - normalement les contrôleurs et les directives (leurs fonctions de liaison et / ou leurs contrôleurs) - peut configurer une " watchExpression " qu'AngularJS évaluera par rapport à cette étendue. Cette évaluation se produit chaque fois qu'AngularJS entre dans sa boucle $ digest (en particulier, la boucle "$ watch list"). Vous pouvez regarder des propriétés individuelles d'étendue, vous pouvez définir une fonction pour regarder deux propriétés ensemble, vous pouvez regarder la longueur d'un tableau, etc.
Lorsque des choses se produisent "à l'intérieur d'AngularJS" - par exemple, vous tapez dans une zone de texte où la liaison de données bidirectionnelle AngularJS est activée (c'est-à-dire, utilise le modèle ng), un rappel $ http se déclenche, etc. - $ apply a déjà été appelé, donc nous 'est à l'intérieur du rectangle "AngularJS" dans la figure ci-dessus. Toutes les watchExpressions seront évaluées (éventuellement plus d'une fois - jusqu'à ce qu'aucun autre changement ne soit détecté).
Lorsque des choses se produisent "en dehors d'AngularJS" - par exemple, vous avez utilisé bind () dans une directive, puis cet événement se déclenche, entraînant l'appel de votre rappel, ou certains déclenchements de rappel enregistrés jQuery - nous sommes toujours dans le rectangle "natif". Si le code de rappel modifie tout ce que regarde $ watch, appelez $ apply pour entrer dans le rectangle AngularJS, provoquant l'exécution de la boucle $ digest, et donc AngularJS remarquera le changement et fera sa magie.
la source
scope.$apply(scope.model)
, je ne comprends pas quelles données sont transférées et comment sont-elles transférées au bon endroit dans le modèle?scope.$apply(scope.model)
sera simplement évaluéscope.model
comme une expression angulaire, puis entrera dans une boucle $ digest. Dans l'article que vous référencez,scope.$apply()
cela suffirait probablement , car le modèle est déjà surveillé. La fonction stop () met à jour le modèle (je crois que toUpdate est une référence à scope.model), puis $ apply est appelé.$watch
sur la page, et le deuxième lien est cassé - pour l'instant, de toute façon). Péniblement, les versions d'archives n'ont pas mis en cache le processus asynchrone ayant créé le contenu.AngularJS étend cette boucle d'événements , créant quelque chose appelé
AngularJS context
.$ watch ()
Chaque fois que vous liez quelque chose dans l'interface utilisateur, vous insérez un
$watch
dans une$watch
liste .Ici, nous avons
$scope.user
, qui est lié à la première entrée, et nous avons$scope.pass
, qui est lié à la seconde. Ce faisant, nous ajoutons deux$watch
es à la$watch
liste .Lorsque notre modèle est chargé, AKA dans la phase de liaison, le compilateur recherchera chaque directive et créera tous les
$watch
es nécessaires.AngularJS fournit
$watch
,$watchcollection
et$watch(true)
. Ci-dessous est un diagramme soigné expliquant les trois prises en profondeur par les observateurs .http://jsfiddle.net/2Lyn0Lkb/
$digest
boucleLorsque le navigateur reçoit un événement qui peut être géré par le contexte AngularJS, la
$digest
boucle est déclenchée. Cette boucle est constituée de deux boucles plus petites. L'un traite la$evalAsync
file d'attente et l'autre le$watch list
. Le$digest
va parcourir la liste de ce$watch
que nous avonsIci, nous n'en avons qu'une
$watch
car ng-click ne crée aucune montre.Nous appuyons sur le bouton.
$digest
boucle s'exécutera et demandera à chaque $ watch les changements.$watch
qui surveillait les changements dans $ scope.name signale un changement, il forcera une autre$digest
boucle.$digest
boucle. Cela signifie que chaque fois que nous écrivons une lettre dans une entrée, la boucle s'exécutera en vérifiant chaque élément$watch
de cette page.$ appliquer ()
Si vous appelez
$apply
lorsqu'un événement est déclenché, il passera par le contexte angulaire, mais si vous ne l'appelez pas, il s'exécutera en dehors de celui-ci. C'est aussi facile que ça.$apply
appellera le$digest()
boucle en interne et itérera sur toutes les montres pour s'assurer que le DOM est mis à jour avec la nouvelle valeur mise à jour.La
$apply()
méthode déclenchera des observateurs sur toute la$scope
chaîne tandis que la$digest()
méthode déclenchera uniquement des observateurs sur le courant$scope
et sonchildren
. Si aucun des$scope
objets supérieurs n'a besoin de connaître les modifications locales, vous pouvez utiliser$digest()
.la source
J'ai trouvé très en profondeur des vidéos qui couvrent
$watch
,$apply
,$digest
et digère cycles: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)
Tutoriel 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).
Dans l'image ci-dessus, "$ scope.c" n'est pas surveillé car il n'est utilisé dans aucune des liaisons de données (dans le balisage). Les deux autres (
$scope.a
et$scope.b
) seront surveillés.À partir de l'image ci-dessus: En fonction de l'événement de navigateur respectif, AngularJS capture l'événement, effectue un cycle de résumé (passe par toutes les surveillances pour les changements), exécute les fonctions de surveillance et met à jour le DOM. S'il ne s'agit pas d'événements de navigateur, le cycle de résumé peut être déclenché manuellement en utilisant
$apply
ou$digest
.En savoir plus
$apply
et$digest
:la source
Il y en a
$watchGroup
et$watchCollection
aussi. Plus précisément,$watchGroup
est vraiment utile si vous souhaitez appeler une fonction pour mettre à jour un objet qui a plusieurs propriétés dans une vue qui n'est pas un objet dom, par exemple une autre vue dans le canevas, WebGL ou une demande de serveur.Ici, le lien de documentation .
la source
$watchCollection
mais je vois que vous l'avez déjà fait. Voici une documentation à ce sujet sur le site AngularJS. Ils offrent un très beau visuel de la$watch
profondeur. Notez que les informations sont proches du bas de la page.Il suffit de terminer la lecture de TOUT ce qui précède, ennuyeux et somnolent (désolé mais c'est vrai). Très technique, en profondeur, détaillé et sec. Pourquoi j'écris? Parce que AngularJS est énorme, de nombreux concepts interconnectés peuvent rendre n'importe qui fou. Je me suis souvent demandé: ne suis-je pas assez intelligent pour les comprendre? Non! C'est parce que si peu de gens peuvent expliquer la technologie dans un langage pour les nuls sans toutes les terminologies! D'accord, laissez-moi essayer:
1) Ce sont toutes des choses événementielles.(J'entends le rire, mais lisez la suite)
Si vous ne savez pas ce qu'est un événement, alors pensez à placer un bouton sur la page, connectez-le avec une fonction en utilisant "on-click", en attendant que les utilisateurs cliquent dessus pour déclencher les actions que vous plantez à l'intérieur du une fonction. Ou pensez au «déclencheur» de SQL Server / Oracle.
2) $ watch est "au clic".
La particularité est qu'elle prend 2 fonctions comme paramètres, la première donne la valeur de l'événement, la seconde prend la valeur en considération ...
3) $ digest est le patron qui vérifie sans relâche , bla-bla-bla mais un bon patron.
4) $ apply vous donne la voie lorsque vous voulez le faire manuellement , comme une preuve de sécurité (au cas où le clic ne se déclenche pas, vous le forcez à s'exécuter.)
Dans un restaurant,
- SERVEURS
sont censés prendre les commandes des clients, c'est
- GESTIONNAIRE courant pour s'assurer que tous les serveurs sont éveillés, sensibles à tout signe de changement de la part des clients. C'est
$digest()
- LE PROPRIÉTAIRE a le pouvoir ultime de conduire tout le monde sur demande, c'est
$apply()
la source