1. Qu'est-ce que la portée?
Scope (http://code.angularjs.org/1.0.2/docs/api/ng.$rootscope.scope) est un objet pointant vers le modèle d'application. Il s'agit également du contexte d'exécution de l'expression (http://www.cnblogs.com/lclao/archive/2012/09/16/2687162.html). La portée est placée dans une hiérarchie de structures DOM similaires à celles de l'application. La portée peut surveiller les événements d'expression et de propagation de surveillance (Watch, Watch).
2. Les caractéristiques de la portée
3. Portée comme modèle de données (portée comme modèle de données)
La portée est le lien entre le contrôleur d'application et la vue. Dans la scène du lien de modèle (http://www.cnblogs.com/lclao/archive/2012/09/04/2669802.html), directive (http://www.cnblogs.com/lclao/archive/2012/09/09/2677190.html) portée. $ watch permet à la directive de connaître les modifications des attributs, donc la directive rend la valeur mise à jour dans le DOM.
Les contrôleurs et les directives font référence à la portée, mais pas les uns aux autres. Cet arrangement sépare le contrôleur de la directive et DOM. C'est un endroit important car il isole le contrôleur de la vue, améliorant considérablement l'histoire de test des applications.
<! Doctype html> <html lang = "zh-cn" ng-app> <éadf> <meta charset = "utf-8"> <itle> data-model </tapt> <style type = "text / css"> .ng-coak {affiche: aucun; } </ style> </ head> <body> <div ng-controller = "myController"> Votre nom: <input type = "text" ng-model = "username" /> <button ng-click = "sayhello ()"> bienvenue </ bouton> <hr /> {{saluer}} </v> <script src = "../ angulaire type = "text / javascript"> </ script> <script type = "text / javascript"> function myController ($ scope) {$ scope.username = "mon petit dada"; $ scope.sayhello = function () {$ scope.greeting = "Hello ~" + $ scope.username + "!"; }; } </ script> </ body> </html>Dans l'exemple ci-dessus, nous pouvons remarquer que MyController attribue l'attribut de nom d'utilisateur dans la portée avec "My Little Dada". Ensuite, Scope informe l'entrée pour l'attribution et la pré-remplissage de la valeur du nom d'utilisateur dans l'entrée. Cela montre comment le contrôleur peut écrire des données dans la portée.
De même, le contrôleur peut attacher le comportement à la portée, tout comme la méthode Sayhello qui est déclenchée lorsque l'utilisateur clique sur le bouton "Bienvenue". La méthode Sayhello peut lire l'attribut de nom d'utilisateur ou créer un attribut de salutation. Cela montre que lorsqu'ils sont liés à un contrôle d'entrée HTML, les propriétés de portée sont automatiquement mises à jour.
Logiquement, l'affichage {{salutation}} implique les deux points suivants:
Recherchez la portée avec le nœud DOM de modèle qui définit l'expression {{salutation}}. Dans cet exemple, cette portée est la même que la portée transmise dans le MyController. (Nous discuterons de la hiérarchie de la portée plus tard)
L'expression de salutation est évaluée par la portée récupérée précédemment, et le résultat est ensuite utilisé comme valeur du texte qui enferme l'élément DOM.
Nous pouvons penser que la portée et ses propres propriétés peuvent être utilisées comme données pour rendre les vues. La portée est la source de vérité unique pour toutes les choses liées.
Du point de vue de la testabilité, la séparation du contrôleur et de la vue est ravie, car elle nous permet de (nous concentrer sur) le comportement de test sans interférence des détails de rendu.
Il ('devrait dire bonjour', function () {var scopeMOCK = {}; var cntl = new MyController (scopeMOCK); // affirme que le nom d'utilisateur est pré-rempli attendu (scopeMock.Username) .toequal ('world'); // Assert que nous lisons un nouveau nom d'utilisateur et saluer SCOPEMOCK.USERNAME = 'Angular'; attendre (ScopeMock.Greeting) .Toequal ('Hello Angular!');});4. Hiérarchies de portée (hiérarchies de portée)
Chaque application angulaire a et une seule portée racine, mais peut avoir plusieurs portées d'enfants.
Une application peut avoir plusieurs portées d'enfants, car certaines directives créeront de nouvelles lunettes d'enfants (voir la documentation de directive pour voir quelles directives peuvent créer de nouvelles lunettes, telles que Ng-Repeat). Lorsque la nouvelle portée sera créée, ils seront ajoutés à la portée des parents en tant que portée de l'enfant. De cette façon, une structure d'arbre similaire au DOM ils sont attachées est créée.
Lorsque Angular évalue {{nom d'utilisateur}}, il examine d'abord la propriété du nom d'utilisateur de la portée associée à l'élément actuel. Si aucune propriété correspondante n'est trouvée, elle recherchera vers le haut la portée des parents jusqu'à ce qu'elle atteigne la portée racine. En JavaScript, ce comportement est appelé "héritage prototype", et la portée de l'enfant est généralement héritée de leur parent.
Cet exemple montre la portée (qu'est-ce qu'elle est) et l'héritage du prototype des propriétés dans l'application.
<! Doctype html> <html lang = "zh-cn" ng -pp> <éadf> <meta charset = "utf-8"> <tight> scope-hierarchies </tapie> <style type = "text / css"> .ng-coak {affiche: aucun; } .ng-scope {Border: 1px Doubed Red; } </ style> </ head> <body> <div ng-controller = "myController"> Manager: {{employee.name}} [{{département}}] <br/> Rapport: <ul> <li ng-repeat = "Employee in Employee.Reports"> {{employee.name}} [{} </ul> <hr /> {{salutation}} </ div> <script src = "../ angular-1.0.1.js" type = "text / javaScript"> </ script> <script type = "text / javascript"> function myController ($ scope) {$ scope.Department = "a une certaine unité"; $ scope.employee = {name: "My Little Dada", rapporte: [{nom: "lclao"}, {name: "Who ^ o ^"}]}; } </ script> </ body> </html>Notez que Angular place automatiquement la classe NG-Scope en éléments qui adhèrent à la portée. <style> est défini dans l'exemple ci-dessus, mettant en évidence la plage de la nouvelle portée à travers la ligne pointillée rouge. Étant donné que le répéteur évalue l'expression {{employee.name}}, la portée de l'enfant est nécessaire, mais selon la portée de l'expression, les différentes lunettes ont des résultats différents. De même, la valeur de {{Department}} est héritée du prototype dans la portée racine. Ce n'est que lorsqu'il y a, l'attribut du département peut être défini.
5. Récupération des lunettes du DOM (récupérer la portée du DOM)
La portée est attachée au DOM en tant qu'attribut de données de portée $ et peut être utilisée pour la récupération à des fins de débogage. (Il est impossible de récupérer la portée de cette manière dans l'application.) L'emplacement de la portée racine attachée au DOM est défini par l'emplacement de la directive NG-App. Habituellement, Ng-App est placé dans l'élément <html>, mais il peut également être placé dans d'autres éléments, par exemple, seule une partie de la vue doit être contrôlée par Angular.
Voir la portée dans le débogueur:
1. Dans le navigateur, cliquez avec le bouton droit sur l'élément qui vous intéresse et sélectionnez "Afficher l'élément". Nous pouvons voir que le débogueur du navigateur met en évidence les éléments que nous avons sélectionnés.
2. Debugger nous permet d'accéder à l'élément actuellement sélectionné via la variable de 0 $ dans la console.
3. Si vous souhaitez voir la portée associée, nous pouvons entrer: Angular.Element (0 $) .scope () dans la console
6. Propagation des événements de portée (propagation des événements de portée)
La portée peut propager les événements d'une manière similaire aux événements DOM. Les événements peuvent être diffusés (http://code.angularjs.org/1.0.2/docs/api/ng.$rootscope.scope#$ $broadcast) à l'enfant Scope ou émettre (http://code.angularjs.org/1.0.2/docs/api/ng.$rootscope.scope#agne) pour faire des parenthèses. (Si la portée actuelle est écoutée, elle sera également exécutée)
<! Doctype html> <html lang = "zh-cn" ng -pp> <éadf> <meta charset = "utf-8"> <t titre> scope-event-propagation </ title> <style type = "text / css"> .ng-col-kak {display: non; } </ style> </ head> <body> <div ng-controller = "myController"> Root Scope Count: {{count}} <ul> <li ng-repeat = "i in [1]" ng-controller = "MyController"> <Button ng-Click = "$ emit ('Myevent") "> $ émure (" MyEvent ") </ bouton </ Myevent") "> $ EMIT (" MyEvent ") </ bouton </ Myevent") "> $ EMIT (" MyEvent ") </ bouton </ Myevent") "> $ EMIT (" MyEvent ") </ Button> </ Myevent") "> $ EMIT (" MyEvent ") </ Button> </ Myevent") "> $ EMIT (" MyEvent ") </ Button> </ Myevent") "> $ EMIT (" MyEvent ") </ Button <aMent ng-click = "$ Broadcast ('MyEvent')"> $ Broadcast ("MyEvent") </ Button> <br/> Count de portée du milieu: {{count}} <ul> <li ng-repeat = "Item in [1,2]" ng-controller = "MyController"> Le nombre de gorgées de la feuille: {{comte}} </ li> </ul> </ div> <script src = "../ angular-1.0.1.js" type = "text / javascript"> </ script> <script type = "text / javaScript"> function myController ($ scope) {$ scope.count = 0; $ scope. $ on ("myEvent", function () {$ scope.count ++;}); } </ script> </ body> </html>7. Cycle de vie de la portée (cycle de vie de la portée)
Dans le flux d'événement normal du navigateur, lorsque le navigateur reçoit l'événement, il exécutera un rappel JavaScript correspondant. Une fois la fonction de rappel exécutée, le navigateur redessier le DOM et reviendra à l'état où vous continuez à attendre l'événement.
Lorsque le navigateur appelle le code JavaScript en dehors de l'environnement d'exécution angulaire, cela signifie qu'Angular ne connaît pas le changement du modèle. Pour gérer correctement la modification du modèle, cette commande doit saisir l'environnement d'exécution angulaire en faisant la méthode $ appliquer. Ce n'est que lorsque les modifications du modèle dans la méthode d'application $ seront correctement comptées par Angular. Par exemple, une directive écoute un événement DOM, tel que Ng-Click, qui doit évaluer l'expression dans la méthode $ Apply.
Après avoir évalué l'expression, la méthode $ applique exécute un $ digest. Dans l'étape $ digest, Scope vérifie toutes les expressions écoutées par $ watch et compare la valeur actuelle avec l'ancienne valeur. La vérification sale est asynchrone. Cela signifie que l'instruction Affectation (par exemple, $ scope.username = "Angular") ne provoquera pas immédiatement une montre $ à notifier, mais la notification de $ Watch sera retardée à l'étape de digestion $. Ce retard est nécessaire car il combine plusieurs mises à jour du modèle dans une notification de montre $, ce qui garantit qu'aucune autre Watch n'est exécutée pendant le processus de notification de Watch $. Si une montre $ modifie la valeur du modèle, elle obligera une augmentation d'un cycle de digestion $.
1) Création (créer une portée)
La portée racine est créée par $ inject Pendant le processus de liaison du modèle, certaines directives créeront une nouvelle portée enfant.
2) Enregistrement de l'observateur (registre d'observation)
Pendant le processus de liaison du modèle, la directive enregistre $ watch in scope. Ces montres seront utilisées comme valeur de propagation du modèle au DOM.
3) Mutation du modèle (changements de modèle)
Pour que les modifications soient détectées correctement, nous devons les envelopper dans la portée. $ Appliquer. (L'API angulaire l'a fait implicitement, donc lorsque vous effectuez un travail synchrone dans le contrôleur ou le travail asynchrone avec $ http ou $ timeout, aucun appel supplémentaire d'application $ n'est requis).
4) Observation de la mutation (surveillance du changement)
À la fin de $ Apply, Angular exécutera un cycle $ digest dans la portée racinaire, qui se propagera à toutes les lunettes d'enfants. Dans le cycle $ Digest, toutes les expressions ou fonctions enregistrées auprès de $ Watch seront vérifiées pour déterminer si le modèle a changé. Si le changement se produit, l'auditeur $ Watch correspondant sera appelé.
5) Destruction de la portée (destruction de la portée)
Lorsque la portée de l'enfant n'est plus nécessaire, il est de la responsabilité du producteur de la portée de l'enfant de le détruire par la portée. $ Destrust () API. Cela arrêtera la propagation des appels $ digest dans la portée de l'enfant, de sorte que la mémoire utilisée par le modèle de portée de l'enfant peut être recyclée par GC (Garbage Collector).
1. Élèves et directives
Pendant la phase de compilation, le compilateur repose sur la directive de correspondance du modèle DOM. Les directives peuvent généralement être divisées en deux catégories:
Les directives d'observation, telles que Dobule-Curly Expression {{Expression}}, enregistrent l'auditeur à l'aide de la méthode $ watch. Chaque fois que l'expression (valeur) change, ces directives doivent être averties pour mettre à jour la vue.
La directive de l'écoute, comme NG-Click, enregistre un auditeur dans le DOM. Lorsque l'auditeur du Dom se déclenche, la directive exécute l'expression pertinente et met à jour la vue en utilisant la méthode $ applique.
Lorsqu'un événement externe (tel que l'action utilisateur, le temporisateur ou le XHR) est entendu, l'expression pertinente doit être appliquée à la portée via la méthode $ applique, afin que tous les auditeurs puissent être mis à jour correctement.
2. Directives qui créent des lunettes
Dans la plupart des cas, la directive et la portée influencent mutuellement, mais aucune nouvelle instance de portée n'est créée. Cependant, certaines directives (telles que NG-contrôleur et Ng-Repeat) créent une nouvelle portée, ajoutant une portée enfant à l'élément DOM correspondant. Nous regardons la portée de tout élément DOM en utilisant Angular.Element (adomelement) .scope ().
3. Contrôleurs et étendues
Dans les cas suivants, la portée et le contrôleur s'influencent mutuellement:
4. Scope $ watch Performance considérations (Scope $ watch Performance considérations)
Dans Angular, c'est une opération courante d'effectuer une vérification sale de la portée pour détecter les changements dans les attributs. Pour ce faire, cela nécessite que la fonction de vérification sale doit être efficace. Soyez prudent que les fonctions de vérification sale ne font aucune opération d'accès DOM, car l'accès DOM est des ordres de grandeur plus lents que d'accès aux propriétés de l'objet JavaScript.
Ce qui précède est les informations sur la portée AngularJS. Nous continuerons d'ajouter des informations pertinentes à l'avenir. Merci pour votre soutien à ce site!