Maison  >  Article  >  interface Web  >  Principe de liaison de données bidirectionnelle AngularJS (tutoriel détaillé)

Principe de liaison de données bidirectionnelle AngularJS (tutoriel détaillé)

亚连
亚连original
2018-06-08 17:57:102560parcourir

Cet article présente principalement l'application de $watch, $apply et $digest basée sur le principe de liaison de données bidirectionnelle d'AngularJS. Il a une certaine valeur de référence. Les amis intéressés peuvent s'y référer

Introduction

Cet article est écrit pour les novices d'AngularJS. Si vous avez déjà une compréhension approfondie de la liaison de données bidirectionnelle d'AngularJS, allez simplement lire le code source.

Contexte

Les développeurs AngularJS veulent tous savoir comment la liaison de données bidirectionnelle est implémentée. Il existe de nombreux termes liés à la liaison de données : $watch, $apply, $digest, dirty-checking, etc. Comment fonctionnent-ils ? Commençons par le début

La liaison de données bidirectionnelle d'AngularJS est forcée par le navigateur

Le navigateur est magnifique, mais en fait, sous l'aspect des données interaction Fils, en raison de « l'inaction » du navigateur, l'actualisation des données du navigateur est devenue un problème. Plus précisément, le navigateur peut facilement écouter un événement, tel que l'utilisateur cliquant sur un bouton ou tapant quelque chose dans la zone de saisie, le navigateur fournit également une API pour les fonctions de rappel d'événement. La fonction de rappel d'événement sera exécutée dans le. interpréteur javascript, mais l'inverse n'est pas si simple. Si les données de l'arrière-plan changent, le navigateur doit être averti et actualisé. Pour les développeurs, c'est un obstacle insurmontable. dois-je faire ? AngularJS apparaît, qui implémente bien la liaison de données bidirectionnelle via $scope. Le principe derrière cela est $watch, $apply, $digest, dirty-checking

$watch queue ($watch list) <.>Littéralement, regarder signifie observer. Chaque fois que vous liez quelque chose au navigateur, un $watch sera inséré dans la file d'attente $watch. Imaginez que $watch soit quelque chose qui puisse détecter les changements dans le modèle qu'il surveille. Par exemple, vous avez le code suivant

Il y a $scope.user, qui est lié à la première zone de saisie, et il y a $scope.pass, qui est lié à la deuxième zone de saisie. ; puis ajoutez deux $watches à la liste $watch :
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />

pour créer un fichier contrôleurs.js avec le code suivant :

fichier html correspondant, index Le code .html est le suivant suit :
app.controller(&#39;MainCtrl&#39;, function($scope) {
 $scope.foo = "Foo";
 $scope.world = "World";
});

Ici, même si deux éléments sont ajoutés à $scope, un seul est lié à l'interface utilisateur, donc un seul $watch est généré :
Hello, {{ World }}
<.>controllers.js

Le fichier html correspondant index.html

app.controller(&#39;MainCtrl&#39;, function($scope) {
 $scope.people = [...];
});

Il semble que plusieurs $watches soient générés. Chaque personne en a deux (un nom, un âge), et ng-repeat est une boucle, donc le total de 10 personnes est (2 * 10) + 1, ce qui signifie qu'il y a 21 $watches. Par conséquent, chaque donnée liée au navigateur générera un $watch. Oui, quand $watch a-t-il été généré ? Revoyons d'abord le principe de chargement d'AngularJS

<ul>
 <li ng-repeat="person in people">
   {{person.name}} - {{person.age}}
 </li>
</ul>

Le principe de chargement d'AngularJS :

Le chargement du modèle d'AngularJS est divisé en deux étapes : la compilation et la liaison. phase, l'interpréteur AngularJS recherchera chaque directive et générera chaque $watch requis. À propos, $watch est généré à ce stade.

Ensuite, commençons à utiliser $digest

$digest loop

Littéralement, digest signifie « digestion ». Je trouve que ce nom est bizarre. Il est étrangement lié au dirty-checking, qui signifie littéralement « sale vérification ». Il vaut mieux ne pas le traduire. L'intention originale de l'auteur original n'est certainement pas celle-ci, elle ne peut être que comprise mais pas exprimée avec des mots !

$digest est une boucle, que fait-il dans la boucle ? $digest parcourt notre $watch. $digest demande à $watch un par un - "Hé, les données que vous avez observées ont-elles changé ?"

Cette traversée est ce qu'on appelle une vérification sale. Maintenant que tous les $watches ont été vérifiés, nous devons nous demander : $watch a-t-il été mis à jour ? Si au moins un a été mis à jour, la boucle sera à nouveau déclenchée jusqu'à ce que tous les $watches soient inchangés. Cela garantit que chaque modèle ne changera plus. N'oubliez pas que si la boucle dépasse 10 fois, une exception sera levée pour éviter une boucle infinie. Lorsque la boucle $digest se termine, le DOM change en conséquence.

Regardez le code, par exemple : contrôleurs.js

fichier html correspondant, index.html

app.controller(&#39;MainCtrl&#39;, function() {
 $scope.name = "Foo";
 $scope.changeFoo = function() {
   $scope.name = "Bar";
 }
});

Il n'y a qu'un seul $watch ici, car ng-Click ne génère pas $watch (la fonction ne changera pas).

{{ name }}
<button ng-click="changeFoo()">Change the name</button>
Le processus d'exécution de $digest est le suivant :

Appuyez sur le bouton dans le navigateur
  1. Le navigateur reçoit un événement ; , entrez le contexte angulaire.
  2. La boucle $digest commence à s'exécuter, demandant si chaque $watch change.
  3. Étant donné que $watch surveillant $scope.name signale un changement, il forcera un autre cycle $digest.
  4. La nouvelle boucle $digest ne détecte aucun changement, auquel cas le navigateur reprend le contrôle et met à jour la partie du DOM correspondant à la nouvelle valeur de $scope.name.
  5. De là, nous pouvons voir un défaut évident d'AngularJS : chaque événement qui entre dans le contexte angulaire exécutera une boucle $digest Même si vous entrez simplement une lettre, $digest parcourra le contexte. page entière. de tous les $watch.

$appliquer l'application

Angular context 是整个Angular的上下文,也可以把它理解为Angular容器,那么,是谁来决定哪些事件可以进入 Angular Context,哪些事件又不能进入呢? 其控制器在 $apply手上。

如果当事件触发时,调用$apply,它会进入angular context,如果没有调用就不会进入。你可能会问:刚才的例子并没有调用$apply,这是怎么回事呢?原来,是Angular背后替你做了。当点击带有ng-click的元素时,事件就会被封装到一个$apply调用中。如果有一个ng-model="foo"的输入框,当输入一个字母 f 时,事件就会这样调用,$apply("foo = 'f';")。

$apply的应用场景

$apply是$scope的一个函数,调用它会强制一次$digest循环。如果当前正在执行$apply循环,则会抛出一个异常。

如果浏览器上数据没有及时刷新,可以通过调用$scope.$apply() 方法,强行刷新一遍。

通过 $watch 监控自己的$scope

<!DOCTYPE html>
<html ng-app="demoApp">
<head>
 <title>test</title>
 <!-- Vendor libraries -->
  <script src="lib/jquery-v1.11.1.js"></script>
  <script src="lib/angular-v1.2.22.js"></script>
  <script src="lib/angular-route-v1.2.22.js"></script>
</head>
<body> 
 <p ng-controller="MainCtrl" >
  <input ng-model="name" />
  Name updated: {{updated}} times.
 </p> 
 <script >
  var demoApp = angular.module(&#39;demoApp&#39;,[]); 
  demoApp.controller(&#39;MainCtrl&#39;, function($scope) {
  $scope.name = "Angular";
  $scope.updated = -1;
  $scope.$watch(&#39;name&#39;, function() {
  $scope.updated++;
 });
});
 </script>
 </body>
</html>

代码说明:

当controller 执行到 $watch时,它会立即调用一次,所以把updated的值设为 -1 。 上输入框中输入字符发生变化时,你会看到 updated 的值随之变化,而且能显示变化的次数。

$watch 检测到的数据变化

小结

我们对 AngularJS的双向数据绑定有了一个初步的认识,对于AngularJS来说,表面上看操作DOM很简单,其实背后有 $watch、$digest 、 $apply 三者在默默地起着作用。这个遍历检查数据是否发生变化的过程,称之为:dirty-checking。 当你了解了这个过程后,你会对它嗤之以鼻,感觉这种方法好low 哦。 确实,如果一个DOM中有 2000- 3000个 watch,页面的渲染速度将会大打折扣。

这个渲染的性能问题怎么解决呢?随着ECMAScript6的到来,Angular 2 通过Object.observe 极大地改善$digest循环的速度。或许,这就是为什么 Angular 团队迫不及待地推出 Angular 2 的原因吧。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue-cli中如何配置babel配置文件

使用node.js实现抖音自动抢红包功能

使用webpack打包处理bundle.js文件过大的问题

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn