Шляхом брудної перевірки $scope
об’єкта
Кутовий підтримує простоту array
спостерігачів у $scope
об’єктах. Якщо ви оглянете будь-яке $scope
, то виявите, що він містить array
дзвінок $$watchers
.
Кожен спостерігач - це object
те, що міститься серед іншого
- Вираз, за яким спостерігає спостерігач. Це може бути просто
attribute
ім'я або щось складніше.
- Останнє відоме значення виразу. Це можна перевірити відповідно до поточного обчисленого значення виразу. Якщо значення різняться, спостерігач запустить функцію та позначить
$scope
як брудне.
- Функція, яка буде виконуватися, якщо спостерігач забруднений.
Як визначаються спостерігачі
У AngularJS існує багато різних способів визначення спостерігача.
Ви можете явно на .$watch
attribute
$scope
$scope.$watch('person.username', validateUnique);
Ви можете розмістити {{}}
інтерполяцію у своєму шаблоні (спостерігач буде створений для вас на поточний $scope
).
<p>username: {{person.username}}</p>
Ви можете попросити таку директиву, як ng-model
визначити спостерігача для вас.
<input ng-model="person.username" />
$digest
Цикл перевіряє всі спостерігач проти останнього значення
Коли ми взаємодіємо з AngularJS через звичайні канали (ng-модель, ng-повторення тощо), директива спричинить цикл дайджесту.
Дайджест циклу - це перше глибинне подолання $scope
всіх його дітей . Для кожного $scope
object
ми повторюємо його $$watchers
array
та оцінюємо всі вирази. Якщо нове значення виразу відрізняється від останнього відомого значення, викликається функція спостерігача. Ця функція може перекомпілювати частину DOM, перерахувати значення $scope
, запустити an AJAX
request
, все, що вам потрібно для цього.
Кожна область обходить і кожен вираз перегляду оцінюється та перевіряється на останнє значення.
Якщо спостерігач спрацьовує, то $scope
брудний
Якщо спрацьовує спостерігач, програма знає, що щось змінилося, і $scope
позначка є брудною.
Функції Watcher можуть змінювати інші атрибути на $scope
батьківщині або на ній $scope
. Якщо одна з $watcher
функцій була запущена, ми не можемо гарантувати, що інші $scope
з них ще чисті, і тому ми виконуємо весь цикл дайджесту знову.
Це пояснюється тим, що AngularJS має двосторонню прив'язку, тому дані можуть передаватися назад в $scope
дерево. Ми можемо змінити значення на вище $scope
, яке вже було засвоєно. Можливо, ми змінимо значення на $rootScope
.
Якщо $digest
брудний, ми виконуємо весь $digest
цикл знову
Ми постійно перебираємо $digest
цикл, поки цикл дайджесту не з’явиться чистим (усі $watch
вирази мають те саме значення, що і в попередньому циклі), або не досягнемо межі дайджесту. За замовчуванням ця межа встановлена на рівні 10.
Якщо ми досягнемо границі дайджесту, AngularJS призведе до помилки в консолі:
10 $digest() iterations reached. Aborting!
Дайджест важкий для машини, але простий для розробника
Як бачите, щоразу, коли щось змінюється у програмі AngularJS, AngularJS перевірятиме кожного спостерігача в $scope
ієрархії, щоб побачити, як реагувати. Для розробника це велика прибутковість продуктивності, тому що зараз вам потрібно майже не писати код електропроводки, AngularJS просто помітить, чи змінилося значення, і зробить решту додатку узгодженою зі зміною.
З точки зору машини, але це дико неефективно і сповільнить наш додаток, якщо ми створимо занадто багато спостерігачів. Місько процитував цифру близько 4000 спостерігачів, перш ніж ваш додаток буде відчувати себе повільно у старих браузерах.
Цю межу легко досягти, наприклад, якщо ви ng-repeat
перевищуєте велику JSON
array
. Ви можете пом'якшити це, використовуючи такі функції, як одноразове прив'язування для складання шаблону без створення спостерігачів.
Як уникнути створення занадто багато спостерігачів
Щоразу, коли ваш користувач взаємодіє з вашим додатком, кожен відвідувач вашої програми буде оцінюватися хоча б один раз. Значна частина оптимізації програми AngularJS - це зменшення кількості спостерігачів у вашому $scope
дереві. Один з простих способів зробити це - одноразове зв’язування .
Якщо у вас є дані, які рідко змінюватимуться, ви можете зв'язати їх лише один раз за допомогою синтаксису ::, наприклад:
<p>{{::person.username}}</p>
або
<p ng-bind="::person.username"></p>
Прив’язка буде ініційована лише тоді, коли буде наданий шаблон, що містить, і дані завантажені в нього $scope
.
Це особливо важливо, коли у вас є ng-repeat
багато предметів.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>