| Пятница, 29 августа, 2014
Метки: AngularJS Комментарии: 0
Итак, после выполнения нашего кода AngularJS сам вызывает функцию $apply() и запускает цикл $digest(). Тогда, в каких ситуациях разработчику необходимо явно вызвать $apply()? В действительности AngularJS делает одну простую вещь. Он отслеживает только те изменения модели, которые сделаны в контексте среды AngularJS, то есть в тех функциях, которые неявно выполняются внутри $apply(). Так реализованы встроенные директивы AngularJS, - любое изменение модели отражается в представлении. Но если вы измените модель вне контекcта AngularJS, то необходимо сообщить среде AngularJS об изменениях посредством явного вызова функции $apply(). Тем самым вы говорите, что изменились некоторые модели и должны быть вызваны все watcher-функции для передачи изменений.
Например, если вы используете не сервис $timeout, а Javascript-функцию setTimeout, чтобы изменить модель, то AngularJS никак не может узнать об этих изменениях. Это тот случай, когда разработчик сам должен прописать вызов функции $apply(), которая инициирует запуск цикла $digest(). Аналогично, если вы пишете директиву, внутри которой реализована функция-событие какого-нибудь DOM-элемента и внутри этой функции изменяются модели, то также нужно вызвать явно $apply(), чтобы изменения произвели нужный эффект.
Рассмотрим пример. Допустим на странице после загрузки через две секунды должно появится сообщение. Реализовали на Javascript так:
Запускаем пример, через две секунды в функции таймера изменяется модель message. Но на представлении это никак не отразилось. Причина в том, что не вызвана явно функция $apply(). Исправим код, как показано ниже:
Теперь мы увидим через две секунды нужное сообщение. Для этого мы просто вызвали нашу функцию, изменяющую модель, внутри $scope.$apply(), которая автоматически запустила цикл $rootScope.$digest().
Замечание: Это гипотетический пример, для показа разницы, на самом деле лучше использовать вместо setTimeout, встроенный в AngularJS сервис $timeout, который автоматически неявно вызовет $apply() и об этом не надо заботиться разработчику.
Также обратим внимание, что можно сделать изменения модели и затем вызвать в конце функцию $apply() без аргументов. Так, как это cделано ниже:
$scope.getMessage = function() { setTimeout(function() { $scope.message = 'Прошло две секунды.'; console.log('message:' + $scope.message); $scope.$apply(); // эта функция запустит $digest }, 2000); };
В этом примере используется безаргументная функция и она работает. Но лучше передавать свою функцию в качестве аргумента в $apply(), так как она выполнится внутри блока try … catch, и все исключения будут передаваться в сервис $exceptionHandler.
Copyright © CodeHint.ru 2013-2025 (v2.4.7 - работает на Angular Universal)Калькулятор инвест-портфеля