$ Apply () и $ Digest () являются двумя основными понятиями в AngularJ, но иногда они сбивают с толку. Чтобы понять, как работает AngularJS, вам сначала нужно понять, как $ применяется () и $ digest (). Эта статья направлена на объяснение того, что такое $ Apply () и $ Digest (), и как они применяются в повседневной кодировке.
1. Исследуйте $ Apply () и $ Digest ()
1.1. Понять двустороннее привязка данных и $ watch ();
AngularJS обеспечивает очень классную функцию, называемую двусторонним привязкой данных, которая значительно упрощает, как мы пишем наш код. Привлечение данных означает, что когда какие -либо данные в представлении изменяются, изменение будет автоматически возвращаться обратно в данные о объеме, что означает, что модель областей будет автоматически обновлена. Точно так же, когда модель областей изменения меняется, данные в представлении обновляются до последнего значения. Так как же это делает Angularjs? Когда вы пишете выражение, такое как {{amodel}}, AngularJS установит для вас наблюдатель на модели областей, которая используется для обновления представления при изменении данных. Наблюдатель здесь такой же, как и наблюдатель, который вы установите в Angularjs:
$ scope. $ watch ('amodel', function (newvalue, oldvalue) {// Обновление DOM с помощью NewValue});Второй параметр, переданный в $ watch (), является функцией обратного вызова, которая будет вызвана при изменении значения амодели. Когда амодель меняется, нетрудно понять, что эта функция обратного вызова будет вызвана для обновления представления, но все еще есть очень важная проблема! Как AngularJs узнает, когда назвать эту функцию обратного вызова? Другими словами, как AngularJs назвал соответствующую функцию обратного вызова, когда он знает, что Amodel изменилась? Будет ли он периодически запустить функцию, чтобы проверить, изменились ли данные в модели областей? Ну, вот где входит петля $ Digest.
В петле $ Digest наблюдатели будут уволены. Когда наблюдатель запускается, AngularJS обнаружит модель прицела. Если это изменится, будет вызвана функция обратного вызова, связанную с наблюдателем. Итак, следующий вопрос - когда петля $ Digest начинается различными способами?
После вызова $ scope. $ Digest () начинается петля $ Digest. Предположим, что вы измените данные в сфере масштаба в функции обработчика, соответствующей директиве NG-клика, AngularJS автоматически запускает A $ Digest Loop, позвонив по телефону $ Digest (). Когда начинается петля $ Digest, он запускает каждого наблюдателя. Эти наблюдатели будут проверять, отличается ли текущее значение модели в области объема от значения модели, рассчитанного в прошлый раз. Если он отличается, соответствующая функция обратного вызова будет выполнена. Результатом вызова этой функции является то, что содержание выражения в представлении (примечание переводчика: например, {{amodel}}) будет обновлен. В дополнение к директиве NG-клика есть некоторые другие встроенные директивы и услуги, которые позволяют вам изменять модели (такие как NG-модель, $ Timeout и т. Д.), И автоматически запускаете A $ Digest Loop.
Пока это неплохо! Однако есть небольшая проблема. В приведенном выше примере AngularJS не вызывает $ Digest () напрямую, но вызывает $ scope. $ Apply (), который вызывает $ rootscope. $ Digest (). Поэтому петля A $ Digest начинается с $ ROOTSCOPE, который затем будет получить доступ ко всем наблюдателям по объему детей.
Примечание: $ scope. $ Apply () автоматически вызовет $ rootscope. $ Digest ().
Метод $ Apply () имеет две формы:
Первый примет функцию в качестве параметра, выполнит функцию и запустит цикл A $ Digest.
Второй тип не примет каких -либо параметров и просто запускает A $ Digest Loop. Мы сразу увидим, почему первая форма лучше.
1.2. Когда вручную вызовать метод $ Apply ()?
Если Angularjs всегда обертывает наш код в функцию и проходите в $ Apply (), чтобы запустить $ Digest Loop, то когда нам нужно вызовать метод $ Apply () вручную? Фактически, AngularJS имеет очень четкое требование для этого, что он отвечает только за автоматическое реагирование на изменения, которые происходят в контексте AngularJS (то есть изменения в моделях, которые происходят в методе $ Apply ()). Вот как это делает встроенная директива AngularJS, поэтому любые изменения модели будут отражены в взгляде. Однако, если вы изменяете модель в любом месте за пределами контекста AngularJS, вам необходимо уведомить AngularJs, позвонив $ Apply () вручную. Это все равно, что рассказывать Angularjs, что вы изменили некоторые модели и надеетесь, что AngularJs помогут вам вызвать наблюдения за правильными ответами.
Например, если вы используете SetTimeout () в JavaScript для обновления модели областей, тогда AngularJS не может узнать, что вы изменили. В этом случае вы обязаны позвонить в $ Apply () и запустить A $ Digest Loop, позвонив в него. Точно так же, если у вас есть директива для установки слушателя событий DOM и изменить некоторые модели в этом слушателе, вам также необходимо позвонить $ Apply () вручную, чтобы убедиться, что изменения будут правильно отражены в представлении.
Давайте посмотрим на пример. Присоединяйтесь, у вас есть страница, на которой будет загружена страница, вы хотите отобразить сообщение через две секунды. Ваша реализация может выглядеть так:
HTML:
<body ng-app = "myApp"> <div ng-controller = "messagecontroller"> отсроченное сообщение: {{message}} </div> </body>JavaScript:
/ * Что происходит без $ Apply () */ angular.module ('myApp', []). Controller ('MessageController', function ($ scope) {$ scope.getMessage = function () {settimeout (function () {$ scope.message = 'atepsed после 3 секунды'; console. } $ scope.getMessage ();Запустив этот пример, вы увидите, что через две секунды консоль показывает обновленную модель, однако представление не обновляется. Может быть, вы уже знаете причину, то есть мы забыли позвонить в метод $ Apply (). Поэтому нам нужно изменить getMessage () следующим образом:
/ * Что происходит с $ apply */angular.module ('myapp', []). Controller ('MessageController', function ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope. $ Применить (function () {// raving inte $ vampe. $ scope.message);Если вы запустите пример выше, вы увидите, что представление также будет обновлено через две секунды. Единственное изменение состоит в том, что наш код теперь обернут в $ scope. $ Apply (), который автоматически запускает $ rootcope. $ Digest (), так что наблюдатели запускаются для обновления представления.
Примечание. Кстати, вы должны использовать службу $ Timeout вместо SetTimeout (), потому что первый вызовет $ Apply () для вас, поэтому вам не нужно называть его вручную.
Кроме того, обратите внимание, что в приведенном выше коде вы также можете вручную позвонить в $ Apply () без параметров после изменения модели, как и следующее:
$ scope.getmessage = function () {settimeout (function () {$ scope.message = 'извлечен через две секунды'; console.log ('Сообщение:' + $ scope.message); $ scope. $ Apply (); // Это триггеры a $ digest}, 2000); };Приведенный выше код использует вторую форму $ Apply (), то есть форма без параметров. Важно помнить, что вы всегда должны использовать метод $ Apply (), который принимает функцию в качестве параметра. Это связано с тем, что когда вы передаете функцию в $ Apply (), функция будет завершена в блок Try ... Catch, поэтому, как только произойдет исключение, исключение будет обработано службой ExceptionHandler.
Ситуация с использованием $ Apply () выглядит следующим образом:
• Обычно вы можете позвонить в $ Apply () на основе любой директивы, предоставленной Angular, которая может использоваться в представлении. Все директивы NG- [Event] (такие как NG-клик, NG-KeyPress) будут звонить $ Apply ().
• Кроме того, вы также можете полагаться на серию угловых встроенных услуг, чтобы позвонить в $ Digest (). Например, служба $ http позвонит $ Apply () после завершения запроса XHR и запуска значения возврата обновления.
• Всякий раз, когда мы вручную обрабатываем события, используем сторонние фреймворки (такие как JQUERY, Facebook API) или Call SetTimeout (), мы можем использовать функцию $ Apply (), чтобы сделать угловой обратный цикл A $ Digest.
Вызовать settimeout ():
<! Doctype html> <html ng-app = "myApp"> <Head> <Title> $ scope. $ Apply () использование </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 = "mytext"> <viv> {{}} </div> <input id Id "btn" <div> {{{}} </div> <входной ID "=" value = "jquery-event"> </input> </div> </body> </html> <script type = "text/javascript"> var mymodule = angular.module ('myApp', []); mymodule.controller ("mytext", function ($ scope) {$ scope.text = "place"; settimeout (function () {$ scope.text = "Значение, установленное после времени"; $ rack. </script>Используйте сторонние фреймворки (например, JQUERY, Facebook API):
<! Doctype html> <html ng-app = "myApp"> <Head> <Title> $ scope. $ Apply () использование </title> <meta charset = "utf-8"> <script src = "https://cdn.jsdelivr.net/jQuery/3.1.0/jquery. src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <div id = "div1" ng-controller = "mytext"> <div> {{text}} </div> <input id = "btn" value = "jquery-event"> </input> </div> </body> </html> <script type = "text/javascript"> var mymodule = angular.module ('myApp', []); mymodule.controller ("mytext", function ($ scope) {$ scope.text = "place";}); $ (function () {$ ("#btn"). click (function () {var $ scope = $ ("#btn"). scope (); $ scope.text = "Значение, установленное в jQuery"; $ scope. $ Apply ();});}) </script>1.3. Сколько раз будет работать петля $ Digest?
Когда запускается $ Digest Loop, наблюдатели будут выполнены, чтобы проверить, изменились ли модели в сфере действия. Если происходит изменение, соответствующая функция прослушивателя будет выполнена. Это связано с важной проблемой. Что, если сама функция слушателя изменит модель областей? Как AngularJs справится с этой ситуацией?
Ответ заключается в том, что петля $ Digest не будет работать только один раз. После того, как текущий цикл заканчивается, он выполнит еще один цикл, чтобы проверить, изменились ли модели. Это грязная проверка, которая используется для обработки изменений модели, которые могут возникнуть при выполнении функции слушателя. Следовательно, петля $ Digest будет продолжать работать до тех пор, пока модель больше не изменится, или цикл $ Digest не достигнет 10 раз. Поэтому старайтесь не изменять модель в функции слушателя как можно больше.
ПРИМЕЧАНИЕ. Цикл $ Digest также будет работать как минимум дважды, даже если в функции слушателя нет модели. Как обсуждалось выше, он будет работать еще раз, чтобы убедиться, что модели не изменяются.
Заключение
Самое важное, что нужно помнить, это то, могут ли AngularJ обнаружить ваши модификации в модели. Если это не может быть обнаружено, то вам нужно позвонить в $ Apply () вручную.
Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!