En vérifiant mal l' $scope
objet
Angular maintient un simple array
observateur dans les $scope
objets. Si vous en inspectez, $scope
vous constaterez qu'il contient un array
appelé $$watchers
.
Chaque observateur est un object
qui contient entre autres
- Une expression que l'observateur surveille. Ce pourrait être simplement un
attribute
nom ou quelque chose de plus compliqué.
- Une dernière valeur connue de l'expression. Cela peut être vérifié par rapport à la valeur calculée actuelle de l'expression. Si les valeurs diffèrent, l'observateur déclenche la fonction et marque le
$scope
comme sale.
- Une fonction qui sera exécutée si l'observateur est sale.
Comment les observateurs sont définis
Il existe de nombreuses façons différentes de définir un observateur dans AngularJS.
Vous pouvez explicitement $watch
un attribute
on $scope
.
$scope.$watch('person.username', validateUnique);
Vous pouvez placer une {{}}
interpolation dans votre modèle (un observateur sera créé pour vous sur le courant $scope
).
<p>username: {{person.username}}</p>
Vous pouvez demander une directive telle que ng-model
définir l'observateur pour vous.
<input ng-model="person.username" />
Le $digest
cycle vérifie tous les observateurs par rapport à leur dernière valeur
Lorsque nous interagissons avec AngularJS via les canaux normaux (ng-model, ng-repeat, etc.), un cycle de résumé sera déclenché par la directive.
Un cycle de digestion est une traversée en profondeur d'abord $scope
et de tous ses enfants . Pour chacun $scope
object
, nous itérons sur son $$watchers
array
et évaluons toutes les expressions. Si la nouvelle valeur d'expression est différente de la dernière valeur connue, la fonction de l'observateur est appelée. Cette fonction peut recompiler une partie du DOM, recalculer une valeur $scope
, déclencher un AJAX
request
, tout ce que vous avez besoin de faire.
Chaque étendue est traversée et chaque expression de surveillance évaluée et vérifiée par rapport à la dernière valeur.
Si un observateur est déclenché, il $scope
est sale
Si un observateur est déclenché, l'application sait que quelque chose a changé et $scope
est marqué comme sale.
Les fonctions d'observateur peuvent modifier d'autres attributs sur $scope
ou sur un parent $scope
. Si une $watcher
fonction a été déclenchée, nous ne pouvons pas garantir que nos autres $scope
sont toujours propres, et nous exécutons donc à nouveau tout le cycle de résumé.
En effet, AngularJS a une liaison bidirectionnelle, de sorte que les données peuvent être transmises dans l' $scope
arborescence. Nous pouvons changer une valeur sur une valeur plus élevée $scope
qui a déjà été digérée. Peut-être que nous changeons une valeur sur le $rootScope
.
Si le $digest
est sale, nous exécutons à $digest
nouveau tout le cycle
Nous parcourons continuellement le $digest
cycle jusqu'à ce que le cycle de résumé soit net (toutes les $watch
expressions ont la même valeur que dans le cycle précédent) ou que nous atteignions la limite de résumé. Par défaut, cette limite est fixée à 10.
Si nous atteignons la limite de résumé, AngularJS déclenchera une erreur dans la console:
10 $digest() iterations reached. Aborting!
Le résumé est dur pour la machine mais facile pour le développeur
Comme vous pouvez le voir, chaque fois que quelque chose change dans une application AngularJS, AngularJS vérifie chaque observateur de la $scope
hiérarchie pour voir comment répondre. Pour un développeur, il s'agit d'une énorme amélioration de la productivité, car vous devez maintenant écrire presque aucun code de câblage, AngularJS remarquera simplement si une valeur a changé et rendra le reste de l'application cohérent avec le changement.
Du point de vue de la machine, cela est extrêmement inefficace et ralentira notre application si nous créons trop d'observateurs. Misko a cité un chiffre d'environ 4000 observateurs avant que votre application ne se sente lente sur les navigateurs plus anciens.
Cette limite est facile à atteindre si vous avez ng-repeat
plus d'un grand JSON
array
par exemple. Vous pouvez éviter cela en utilisant des fonctionnalités telles que la liaison unique pour compiler un modèle sans créer d'observateurs.
Comment éviter de créer trop d'observateurs
Chaque fois que votre utilisateur interagit avec votre application, chaque observateur de votre application sera évalué au moins une fois. Une grande partie de l'optimisation d'une application AngularJS consiste à réduire le nombre d'observateurs dans votre $scope
arbre. Une façon simple de le faire est d'utiliser une liaison unique .
Si vous avez des données qui changeront rarement, vous ne pouvez les lier qu'une seule fois en utilisant la syntaxe ::, comme ceci:
<p>{{::person.username}}</p>
ou
<p ng-bind="::person.username"></p>
La liaison ne sera déclenchée que lorsque le modèle conteneur sera rendu et les données chargées dans $scope
.
Ceci est particulièrement important lorsque vous en avez un ng-repeat
avec de nombreux articles.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>