Як працює прив'язка даних у AngularJS?


1956

Як працює прив'язка даних у AngularJSрамках?

Я не знайшов технічних деталей на їхньому сайті . Більш-менш зрозуміло, як це працює, коли дані поширюються від перегляду до моделі. Але як AngularJS відстежує зміни властивостей моделі без сетерів та геттерів?

Я виявив, що є спостерігачі JavaScript, які можуть зробити цю роботу. Але вони не підтримуються в Internet Explorer 6 та Internet Explorer 7 . Тож як AngularJS знає, що я змінив, наприклад, наступне, і відобразив цю зміну на поданні?

myobject.myproperty="new value";

10
Майте на увазі, що з-за кутового 1.0.0rc1 вам потрібно вказати ng-model-instant ( docs-next.angularjs.org/api/… ), щоб оновити модернізацію постійно. В іншому випадку він буде оновлений події розмиття.
Сотомайор

8
Посилання Марчелло, очевидно , зламана, так ось вона знову: github.com/mhevery/angular.js/blob/master/docs/content/guide / ...
сволочі

6
@orian, це посилання погано. оновлено до (я припускаю) те саме - docs.angularjs.org/guide/databinding
Кевін Мередіт

11
Для тих, хто все ще читає це запитання, зауважте, що Angular 2.0 сильно змінив те, як вони починають зв'язувати дані з моменту Angular 1.x, щоб працювати з веб-компонентами та вирішувати багато питань у відповідях нижче.
серпня

Відповіді:


2744

AngularJS запам'ятовує значення і порівнює його з попереднім значенням. Це основна брудна перевірка. Якщо є зміна значення, то воно запускає подію зміни.

$apply()Метод, який є те , що ви називаєте , коли ви перехід від НЕ AngularJS світу в AngularJS світі, дзвінки $digest(). Дайджест - це звичайна стара брудна перевірка. Він працює у всіх браузерах і є цілком передбачуваним.

Для порівняння брудної перевірки (AngularJS) проти зміни слухачів ( KnockoutJS та Backbone.js ): Хоча брудна перевірка може здатися простою і навіть неефективною (я звернуся до цього пізніше), виявляється, що вона семантично коректна весь час, у той час як слухачі змін мають безліч дивних кутових випадків і потрібні такі речі, як відстеження залежності, щоб зробити його більш семантично правильним. Відстеження залежності KnockoutJS - це розумна функція для проблеми, якої немає у AngularJS.

Проблеми зі слухачами змін:

  • Синтаксис жорстокий, оскільки веб-переглядачі не підтримують його в оригіналі. Так, є проксі-сервери, але вони не семантично коректні у всіх випадках, і, звичайно, немає проксі-серверів у старих браузерах. Суть полягає в тому, що брудна перевірка дозволяє вам робити POJO , тоді як KnockoutJS та Backbone.js змушують вас успадковувати їхні класи та отримувати доступ до своїх даних через приладдя.
  • Зміна злиття. Припустимо, у вас є масив елементів. Скажіть, що ви хочете додати елементи в масив, як ви робите циклічне додавання, кожного разу, коли ви додаєте, ви запускаєте події на зміну, що надає інтерфейс користувача. Це дуже погано для продуктивності. Що потрібно - оновити інтерфейс користувача лише один раз, наприкінці. Події змін є надто дрібними.
  • Заміна слухачів негайно запускається на сетер, що є проблемою, оскільки слухач змін може додатково змінювати дані, що призводить до більшої кількості змін. Це погано, оскільки на вашому стеку може статися відразу кілька змін змін. Припустимо, у вас є два масиви, які потрібно зберігати синхронізовано з будь-якої причини. Ви можете додати лише те чи інше, але кожен раз, коли ви додаєте, ви поводите зміну події, яка тепер має непослідовний погляд на світ. Це дуже схожа проблема з блокуванням потоку, якого уникає JavaScript, оскільки кожен зворотний виклик виконується виключно і до завершення. Події зміни це порушують, оскільки сетери можуть мати далекосяжні наслідки, які не є задуманими та неочевидними, що створює проблему з потоком знову. Виявляється, що ви хочете зробити, це затримати виконання слухача та гарантувати,

А як щодо продуктивності?

Тож може здатися, що ми повільні, оскільки брудна перевірка неефективна. Тут нам потрібно дивитися на реальні числа, а не просто мати теоретичні аргументи, але спочатку давайте визначимо деякі обмеження.

Люди:

  • Повільне - все швидше, ніж 50 мс, непомітно для людини, і тому може вважатися "миттєвим".

  • Обмежено - Ви не можете реально показати більше 2000 відомостей людині на одній сторінці. Ніщо більше, ніж це, справді поганий інтерфейс користувача, і людина все одно не може це обробити.

Тож справжнє запитання таке: скільки порівнянь можна виконати в браузері за 50 мс? На це складний питання відповісти, оскільки багато факторів грають, але ось тестовий випадок: http://jsperf.com/angularjs-digest/6, який створює 10 000 спостерігачів. Для сучасного браузера це займає трохи менше 6 мс. В Internet Explorer 8 потрібно близько 40 мс. Як бачите, це не проблема навіть у повільних браузерах. Є застереження: порівняння повинні бути простими, щоб вписатись у часовий ліміт ... На жаль, занадто просто додати повільне порівняння в AngularJS, тому легко будувати повільні програми, коли ви не знаєте, що ви роблять. Але ми сподіваємось отримати відповідь, надавши інструментальний модуль, який би показав вам, які є повільні порівняння.

Виявляється, у відеоіграх та графічних процесорах використовується брудний підхід, особливо тому, що він є послідовним. Поки вони перевищують частоту оновлення монітора (як правило, 50-60 Гц або кожні 16,6-20 мс), будь-яка продуктивність над цим є марною, тож вам краще намалювати більше матеріалів, ніж підвищити FPS.


32
@Mark - так, в КО ви просто додаєте .extend ({throttle: 500}), щоб чекати 500 мілісекунд після останньої події зміни, перш ніж діяти на нього.
Даніель Ервікер

158
Ця вся відповідь чудова, окрім "Поки вони отримують 50 кадрів в секунду, будь-яка продуктивність над цим є марною, оскільки людське око не може цього оцінити, тож вам краще намалювати більше матеріалів, ніж підвищити кадр в секунду вище". Це твердження є абсолютно невірним залежно від вашої заявки. Око напевно може оцінити більше 50 кадрів в секунду, і тому що різні проблеми з VR показують (читайте будь-яку останню з Джон Кармака або Майкла Абраша, особливо останню розмову про GDC 2013 VR), 50 кадрів в секунду насправді занадто повільно. Крім цього, ваша відповідь чудова. Я просто не хочу, щоб дезінформація поширювалася.
Нейт Банді

10
@DavidRivers нас - це так само, як і в utorrent 1µs = 0,000001s
Thorgeir

33
Заява можна легко сказати зворотно, оскільки "Брудна перевірка - це розумна функція для проблеми, якої немає в нокауті". ES6 використовує спостереження, а кутовий позбавляється від брудної перевірки. Реальний світ наздогнав цю відповідь і показав, що вона помилкова.
конічне

17
"Що-небудь швидше, ніж 50 мс, непомітно для людини", це неправда. Під час тестування ми виявили, що наші клієнти можуть легко розрізнити затримку оновлення 50 мс (20 кад / с) та затримку оновлення 16,6 мс (60 кадрів в секунду). Сцени, що працюють з колишньою швидкістю, постійно отримують бідніші загальні рейтинги "як він почувався", навіть коли люди не свідомо реєстрували кадр.
Crashworks

323

Місько вже дав чудову характеристику того, як працюють прив'язки даних, але я хотів би додати свій погляд на питання про ефективність із прив'язкою даних.

Як заявив Місько, близько 2000 прив’язок - це те, де ви починаєте бачити проблеми, але у вас все одно не повинно бути більше 2000 відомостей на сторінці. Це може бути правдою, але не кожна прив'язка даних видно користувачеві. Після того як ви почнете створювати будь-який віджет або сітку даних з двостороннім прив'язкою, ви можете легко потрапити на 2000 прив’язок, не маючи поганого UX.

Розглянемо, наприклад, комбінований вікно, куди можна вводити текст, щоб відфільтрувати доступні параметри. Цей тип контролю може мати ~ 150 предметів і все ще бути корисним для використання. Якщо він має якусь додаткову функцію (наприклад, певний клас у вибраному на даний момент варіант), ви починаєте отримувати 3-5 прив’язок за варіант. Помістіть три ці віджети на сторінку (наприклад, один для вибору країни, другий для вибору міста у зазначеній країні, а третій для вибору готелю), і ви вже десь між 1000 і 2000 прив’язками.

Або розгляньте сітку даних у корпоративному веб-додатку. 50 рядків на сторінці - це нерозумно, кожен з яких може мати 10-20 стовпців. Якщо ви будуєте це за допомогою ng-повторів та / або маєте інформацію в деяких клітинках, які використовують деякі прив'язки, ви можете наблизитись до 2000 прив’язок лише з цією сіткою.

Я вважаю це великою проблемою при роботі з AngularJS, і єдине рішення, яке мені вдалося знайти досі, - це створити віджети без використання двостороннього прив'язки, замість того, щоб використовувати ngOnce, скасовувати реєстрацію спостерігачів та подібні хитрощі, або конструювати директиви, які будують DOM за допомогою маніпуляції jQuery та DOM. Я відчуваю, що це перемагає мета використання в першу чергу Angular.

Я хотів би почути пропозиції щодо інших способів вирішити це, але, можливо, я повинен написати власне запитання. Я хотів викласти це в коментарі, але це виявилося занадто довго для цього ...

TL; DR
Прив'язка даних може спричинити проблеми з продуктивністю на складних сторінках.


26
Так, я другий. Основна відповідальність нашого додатка - відображати зв’язки між різними об'єктами. Дана сторінка може мати 10 розділів. У кожному розділі є таблиця. Кожна таблиця має 2-5 фільтрів типу "головка". Кожна таблиця має 2-5 стовпців, у кожному - по 10 рядків. Дуже швидко ми стикаємося з проблемами, пов'язаними з парфумом, і вибираємо варіанти "подібних трюків".
Скотт Сілві

10
Чи справедливо сказати, що Angular стосується не лише прив'язки даних, а деякі додатки можуть не захотіти використовувати цю функцію саме з тих причин, які викликали інші? Я вважаю, що підхід DI та модульність сам по собі вартий багато; магічне автоматичне прив’язування приємно, але в кожній існуючій реалізації є компроміси продуктивності. Спосіб Angular напевно перевершує більшість веб-додатків CRUD, і люди просто б’ють об стіну, намагаючись довести її до крайності. Було б непогано підтримувати альтернативний метод прослуховування подій, але, можливо, це принципово занадто складно для однієї рамки?
Джейсон Бойд

8
Кутовий тепер має один спосіб та прив'язування даних одноразово, щоб допомогти у вирішенні цієї проблеми. Крім того, тепер він має індекси для вашого джерела ретранслятора, що дозволяє вам змінювати список, не будуючи dom для всього вмісту.
Gaute Løken

6
@MW. Чесно кажучи, я думав, що зв'язування колись було в основі. Але, здається, це не так. Це просто те, що ви можете зробити, коли пишете власні директиви, в основному пов'язуючи речі, не переглядаючи їх. Однак є УБ мод для нього: github.com/pasvaz/bindonce
Gaute Løken

9
Крик майбутнього для тих, хто читає це: колись прив'язка тепер є основною особливістю у Angular v1.3, читати більше тут: docs.angularjs.org/guide/expression
Nobita

158

Шляхом брудної перевірки $scopeоб’єкта

Кутовий підтримує простоту arrayспостерігачів у $scopeоб’єктах. Якщо ви оглянете будь-яке $scope, то виявите, що він містить arrayдзвінок $$watchers.

Кожен спостерігач - це objectте, що міститься серед іншого

  1. Вираз, за ​​яким спостерігає спостерігач. Це може бути просто attributeім'я або щось складніше.
  2. Останнє відоме значення виразу. Це можна перевірити відповідно до поточного обчисленого значення виразу. Якщо значення різняться, спостерігач запустить функцію та позначить $scopeяк брудне.
  3. Функція, яка буде виконуватися, якщо спостерігач забруднений.

Як визначаються спостерігачі

У AngularJS існує багато різних способів визначення спостерігача.

  • Ви можете явно на .$watchattribute$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>

Дякуємо @ user2864740 - хоча правильно, що відповідь Місько має бути вгорі. Він знає рамки краще, ніж хто-небудь, і це досить круто, що він взаємодіє з Stack Overflow ..
суперлюмінація

4
Я не погоджуюся з тим, що зазначена відповідь повинна бути вгорі; є різниця між тим, що щось знати, і написати відповідну / детальну відповідь на конкретне питання. Є кращі способи отримати похвалу. У всякому разі ..
користувач2864740

1
Я не сумніваюся, що це правда, але запитання і відповіді на відповіді :)
user2864740

3
Хороша відповідь, що висвітлює, як поводиться брудний чек і що його насправді оцінює, одне було не надто ясно у відповіді Місько.
стридер

3
Чудова і детальна відповідь. @superluminary, дякую за таку відповідь. Більше того, прочитавши цю відповідь, я приходжу до того, що ми не мусимо додавати неідентичне вираження як вираз, який спостерігається.
Мангу Сінгх Раджпурохіт

81

Це моє основне розуміння. Це може бути неправильним!

  1. Елементи переглядаються шляхом передачі функції (повернення речі, яку слід спостерігати) $watchметоду.
  2. Зміни в переглянуті елементи повинні бути внесені в блок коду, обгорнутого $applyметодом.
  3. В кінці $applyв $digestвиклику методу , який проходить через кожен з годинника і перевіряє , якщо вони змінилися з моменту останнього $digestRAN.
  4. Якщо будь-які зміни знайдені, то дайджест знову викликається, поки всі зміни не стабілізуються.

При нормальній розробці синтаксис зв’язування даних у HTML повідомляє компілятору AngularJS створити годинник для вас, а методи контролера вже запущені всередині $apply. Тож для розробника додатків все прозоро.


4
коли запускається метод застосування?
numan salati

3
@EliseuMonar Цикл дайджесту працює внаслідок якоїсь події або виклику $ apply (), він не викликається періодично на основі таймера. дивіться, як працює функція $ watch AngularJS? і як працює зв'язування та перетравлення в AngularJS?
adl

1
@remi, мене не хвилює остання версія AngularJS. Вони вже використовують проксі або Object.observe? Якщо ні, вони все ще знаходяться в брудній ері перевірки, яка створює приурочений цикл, щоб побачити, чи змінилися атрибути моделі.
Eliseu Monar dos Santos

1
я читав, що дайджест працюватиме максимум в десять разів sitepoint.com/understanding-angulars-apply-digest
user137717

62

Я на деякий час дивувався цьому. Як без налаштування, як AngularJSпомічає зміни $scopeоб’єкта? Чи опитує їх?

Насправді це так: будь-яке "звичайне" місце, де ви модифікували модель, вже викликалося з кишок AngularJS, тому воно автоматично закликає $applyвас після запуску вашого коду. Скажімо, ваш контролер має метод, який підключений до ng-clickякогось елемента. Оскільки ви проводите AngularJSспільний виклик цього методу для вас, у нього є шанс зробити $applyвідповідне місце у відповідному місці. Крім того, для виразів, які відображаються прямо у поглядах, вони виконуються AngularJSтак, як це робиться $apply.

Коли в документації йдеться про необхідність виклику $applyвручну для коду поза межамиAngularJS , це говорить про код, який при запуску не випливає з AngularJSсебе в стеку викликів.


32

Пояснення з малюнками:

Прив'язка даних потребує відображення

Посилання в області застосування не є саме посиланням у шаблоні. Коли ви зв'язуєте дані два об'єкти, вам потрібен третій, який слухає перший і модифікує другий.

введіть тут опис зображення

Тут, коли ви модифікуєте <input>, ви торкаєтеся даних-ref3 . І класичний механізм зв’язування даних змінить data-ref4 . То як {{data}}рухатимуться інші вирази?

Події призводять до дайджесту $ ()

введіть тут опис зображення

Кутовий підтримує oldValueі newValueкожну палітурку. І після кожної кутової події знаменитий $digest()цикл перевірятиме список спостереження, щоб побачити, чи щось змінилося. Ці кутові події є ng-click, ng-change, $httpзавершено ... The $digest()цикл буде до тих пір , як будь-який oldValueвідрізняється від newValue.

На попередньому малюнку ви помітите, що дані-ref1 та data-ref2 змінилися.

Висновки

Це трохи схоже на Яйце і курку. Ніколи не знаєш, хто починає, але, сподіваємось, це працює більшу частину часу, як очікувалося.

Інший момент полягає в тому, що ви можете легко зрозуміти вплив глибокого простого прив'язки на пам'ять і процесор. Сподіваємось, Десктопи досить жирні, щоб впоратися з цим. Мобільні телефони не такі сильні.


22

Очевидно, немає періодичної перевірки Scopeнаявності будь-яких змін об'єктів, що додаються до неї. Не всі об’єкти, що додаються до сфери перегляду, переглядаються. Масштаб прототипно підтримує $$ спостерігачів . Scopeлише повторюється через це, $$watchersколи $digestвикликається.

Angular додає спостерігача до $$ спостерігачів для кожного з них

  1. {{express}} - у ваших шаблонах (і в будь-якому іншому місці, де є вираз) або коли ми визначаємо ng-модель.
  2. $ range. $ watch ('вираз / функція') - у вашому JavaScript ми можемо просто приєднати об'єкт області для кутового перегляду.

Функція $ watch займає три параметри:

  1. По-перше, це функція спостерігача, яка просто повертає об'єкт, або ми можемо просто додати вираз.

  2. Друга - це функція слухача, яка буде викликана, коли відбудеться зміна об'єкта. У цій функції будуть реалізовані всі речі, такі як зміни DOM.

  3. Третій - необов'язковий параметр, який приймає булеве значення. Якщо його справжнє, кутове глибоке спостерігає за об'єктом, а якщо його помилковий кутовий просто робить посилання, спостерігаючи на об'єкт. Грубе впровадження $ watch виглядає приблизно так

Scope.prototype.$watch = function(watchFn, listenerFn) {
   var watcher = {
       watchFn: watchFn,
       listenerFn: listenerFn || function() { },
       last: initWatchVal  // initWatchVal is typically undefined
   };
   this.$$watchers.push(watcher); // pushing the Watcher Object to Watchers  
};

У кутовій є цікава річ під назвою Цикл дайджесту. Цикл дайджесту $ починається в результаті виклику до $ range. $ Digest (). Припустимо, що ви змінюєте модель діапазону $ у функції обробника через директиву ng-click. У такому випадку AngularJS автоматично запускає цикл перетворення $ за допомогою виклику $ digest (). Крім ng-клацання, є ще кілька вбудованих директив / служб, які дозволяють змінювати моделі (наприклад, ng-модель, $ timeout тощо). і автоматично запускати цикл дайджесту $. Груба реалізація $ дайджесту виглядає приблизно так.

Scope.prototype.$digest = function() {
      var dirty;
      do {
          dirty = this.$$digestOnce();
      } while (dirty);
}
Scope.prototype.$$digestOnce = function() {
   var self = this;
   var newValue, oldValue, dirty;
   _.forEach(this.$$watchers, function(watcher) {
          newValue = watcher.watchFn(self);
          oldValue = watcher.last;   // It just remembers the last value for dirty checking
          if (newValue !== oldValue) { //Dirty checking of References 
   // For Deep checking the object , code of Value     
   // based checking of Object should be implemented here
             watcher.last = newValue;
             watcher.listenerFn(newValue,
                  (oldValue === initWatchVal ? newValue : oldValue),
                   self);
          dirty = true;
          }
     });
   return dirty;
 };

Якщо ми використовуємо функцію setTimeout () JavaScript для оновлення моделі області, Angular не може знати, що ви можете змінити. У цьому випадку наша відповідальність за виклик $ apply () вручну, що запускає цикл перебору $. Аналогічно, якщо у вас є директива, яка встановлює слухач подій DOM і змінює деякі моделі всередині функції обробника, вам потрібно викликати $ apply (), щоб переконатися, що зміни набули чинності. Велика ідея $ apply полягає в тому, що ми можемо виконати якийсь код, який не знає Angular, який може все-таки змінити речі в області застосування. Якщо ми обернемо цей код у $ apply, він подбає про виклик $ digest (). Груба реалізація $ apply ().

Scope.prototype.$apply = function(expr) {
       try {
         return this.$eval(expr); //Evaluating code in the context of Scope
       } finally {
         this.$digest();
       }
};

15

AngularJS обробляє механізм зв’язування даних за допомогою трьох потужних функцій: $ watch () , $ digest () і $ apply () . Більшу частину часу AngularJS буде викликати $ range. $ Watch () та $ range. $ Digest (), але в деяких випадках вам, можливо, доведеться викликати ці функції вручну, щоб оновити нові значення.

$ watch () : -

Ця функція використовується для спостереження за змінами змінної в області $ $. Він приймає три параметри: вираз, слухач і об'єкт рівності, де слухач і об'єкт рівності - необов'язкові параметри.

$ дайджест () -

Ця функція повторюється через усі годинники в об’єкті $ range та його дочірніх об'єктах $ range
(якщо такі є). Коли $ digest () переходить на годинник, він перевіряє, чи змінилося значення виразу. Якщо значення змінилося, AngularJS викликає слухача з новим значенням і старим значенням. Функція $ digest () викликається, коли AngularJS вважає це необхідним. Наприклад, після натискання кнопки або після дзвінка AJAX. Можливо, у вас є випадки, коли AngularJS не викликає для вас функцію $ digest (). У такому випадку вам доведеться телефонувати самі.

$ apply () -

Angular робить автоматичне оновлення лише ті зміни в моделях, які знаходяться в контексті AngularJS. Коли ви змінюєте будь-яку модель за межами кутового контексту (наприклад, події DOM браузера, setTimeout, XHR або сторонні бібліотеки), тоді вам потрібно повідомити Angular про зміни, зателефонувавши в $ apply () вручну. Коли виклик функції $ apply () завершує внутрішній виклик AngularJS викликів $ digest (), тож усі прив'язки даних оновлюються.


7

Бувало, що мені потрібно було пов’язати модель даних людини з формою, що я зробив - це пряме відображення даних із формою.

Наприклад, якщо модель мала щось подібне:

$scope.model.people.name

Контрольний вхід форми:

<input type="text" name="namePeople" model="model.people.name">

Таким чином, якщо ви зміните значення контролера об'єкта, це відображатиметься автоматично у поданні.

Приклад, коли я передав, що модель оновлюється з даних сервера, - це коли ви запитуєте поштовий індекс та поштовий індекс на основі письмових завантажень списку колоній та міст, пов’язаних із цим представленням, і за замовчуванням встановлюєте перше значення з користувачем. І це я дуже добре працював. Що трапляється, це те, що angularJSіноді потрібно кілька секунд, щоб оновити модель, для цього можна поставити спінер під час відображення даних.


14
Я прочитав цю відповідь 5 разів, і досі не розумію, що тут мається на увазі.
сбедулін

1
Відповідь здається для мене загадкою
Аман

6
  1. Одностороння прив'язка даних - це підхід, коли значення береться з моделі даних і вставляється в елемент HTML. Немає можливості оновити модель з виду. Він використовується в класичних шаблонових системах. Ці системи пов'язують дані лише в одному напрямку.

  2. Обв’язання даних у кутових додатках - це автоматична синхронізація даних між моделлю та компонентами перегляду.

Прив'язка даних дозволяє розглядати модель як єдине джерело правди у вашій програмі. Вид - це проекція моделі в усі часи. Якщо модель буде змінена, вигляд відображає зміну і навпаки.


5

Ось приклад зв’язування даних з AngularJS, використовуючи поле введення. Я поясню пізніше

HTML-код

<div ng-app="myApp" ng-controller="myCtrl" class="formInput">
     <input type="text" ng-model="watchInput" Placeholder="type something"/>
     <p>{{watchInput}}</p> 
</div>

AngularJS Code

myApp = angular.module ("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
  //Your Controller code goes here
}]);

Як ви бачите в прикладі вище, AngularJS використовує ng-modelдля прослуховування та перегляду того, що відбувається з елементами HTML, особливо на inputполях. Коли щось відбувається, роби щось. У нашому випадку ng-modelприв'язується до нашого погляду, використовуючи позначення вуса {{}}. Що вводиться всередину поля введення, миттєво відображатиметься на екрані. І ось у чому краса прив'язки даних, використовуючи AngularJS у найпростішому вигляді.

Сподіваюсь, це допомагає.

Дивіться робочий приклад тут на Codepen


5

AngularJs підтримує двостороння зв'язування даних .
Значить, ви можете отримати доступ до даних Перегляд -> Контролер і контролер -> Перегляд

Для екс.

1)

// If $scope have some value in Controller. 
$scope.name = "Peter";

// HTML
<div> {{ name }} </div>

О / П

Peter

Ви можете прив’язати дані в " ng-modelLike": -
2)

<input ng-model="name" />

<div> {{ name }} </div>

Ось у наведеному вище прикладі все, що введе користувач, він буде видно в <div>тегу.

Якщо ви хочете прив'язати вхід з HTML до контролера: -
3)

<form name="myForm" ng-submit="registration()">
   <label> Name </lbel>
   <input ng-model="name" />
</form>

Тут, якщо ви хочете використовувати вхід nameв контролері,

$scope.name = {};

$scope.registration = function() {
   console.log("You will get the name here ", $scope.name);
};

ng-modelпов'язує наш погляд і надає його у вираз {{ }}.
ng-modelце дані, які відображаються користувачеві у вікні перегляду та з якими користувач взаємодіє.
Тому легко пов'язувати дані в AngularJs.


4

Angular.js створює спостерігач для кожної моделі, яку ми створюємо в перегляді. Щоразу, коли модель змінюється, до моделі додається клас "брудний", тому спостерігач буде спостерігати за всіма моделями, які мають клас "ng-брудними", і оновлювати свої значення в контролері та навпаки.


3

прив'язка даних:

Що таке зв'язування даних?

Кожного разу, коли користувач змінює дані в представленні даних, відбувається оновлення цієї зміни в області застосування, і навпаки.

Як це можливо?

Коротка відповідь : За допомогою дайджесту циклу.

Опис: Angular js встановлює вахту на модель сфери, яка запускає функцію слухача, якщо є зміна моделі.

$scope.$watch('modelVar' , function(newValue,oldValue){

// Код оновлення Dom з новим значенням

});

Отже, коли і як називається функція спостерігача?

Функція спостерігача називається частиною дайджест-циклу.

Цикл дайджесту називається автоматично запускається як частина кутових js, вбудованих у директиви / послуги, такі як ng-модель, ng-bind, $ timeout, ng-click та інші .., які дозволяють запустити цикл дайджесту.

Функція дайджесту циклу:

$scope.$digest() -> digest cycle against the current scope.
$scope.$apply() -> digest cycle against the parent scope 

тобто$rootScope.$apply()

Примітка: $ apply () дорівнює $ rootScope. $ Digest () це означає, що брудна перевірка починається прямо від кореня чи верху або батьківської області вниз до всіх дочірніх областей $ у кутовій програмі js.

Вищезазначені функції працюють у IE браузерів для згаданих версій також лише переконуючись, що ваше додаток є програмою angular js, що означає, що ви використовуєте файл сценарію рамки angularjs, на який посилається тег сценарію.

Дякую.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.