Всім доброго часу доби.
Якщо ви задаєтеся одним з таких запитань:
- що таке динамічне пов'язування даних?
- як працює зв'язування даних в AngularJS або йому подібних MVVM-фреймворках?
- чим, чорт забирай, MPV відрізняється від MVVM?
Тоді вам під кат...
І так... в кінці, як завжди, посилання на код;)
Про MVP:
MVP (Model-View-Presenter) - це один з найпоширеніших шаблонів проектування UI.
Суть його полягає в наступному:
- Presenter підписується на події від View
- View емітує події
- Presenter ловить події і робить запити в Model
- При отриманні відповіді від Model, Presenter оновлює View
Відразу ж в очі кидається ключова відмінність MVP від MVC: MVP, на відміну від MVC, має двосторонній зв'язок з View.
Запам'ятаємо і підемо далі...
Про MVVM:
MVVM (Model-View-ViewModel) - це покращена форма MVP, при чому межа між ними така тонка, що іноді думаєш: "О, небо! За що ти так зі мною? "
Зараз поясню що я маю на увазі.
Суть MVVM полягає в наступному:
- ModelView підписується на події від View
- View емітує події
- ModelView ловить події і робить запити в Model
- При отриманні відповіді від Model, ModelView оновлює View
Якщо відкинути формальності, то так воно і є. Тому я і сказав, що межа між MVP і MVVM дуже тонка.
Глобально, різниця лише в тому, що MVVM реалізує більш гнучкий слухач подій від View.
При чому реалізує таким чином, що стає доступним так зване декларативне динамічне пов'язування даних.
Про динамічне зв'язування даних:
Це такий механізм, при якому, змінивши значення моделі з будь-якого боку (з боку View або Model), ця зміна моментально набуде чинності. Тобто, змінивши значення в Model (в MVVM - ViewModel частково бере на себе функцію моделі), воно відразу відобразиться у View і навпаки.
Ви можете запитати: «Якщо в MVP є двосторонній зв'язок між View і Presenter, то чому ми не можемо реалізувати динамічне пов'язування даних на MVP?».
Відповідь дуже проста - можемо!
По суті, MVP вже передбачає динамічне зв'язування даних в тій чи іншій мірі.
І, якщо MVP це чисто імперативний підхід до зв'язування даних, то MVVM - декларативний.
Ось і вся різниця.
Але суть у них одна і та ж!
Про реалізацію:
Тепер розглянемо питання, пов'язані з реалізацією динамічного пов'язування даних.
Почнемо з того, що, на поточний момент, браузер не здатний динамічно відстежувати зміну значень в змінних.
Звичайно, є така штука як Object.observe (), але ця річ, поки ще, не є частиною стандарту.
Тому виходимо з того, що
браузер не здатний динамічно відстежувати зміну значень у змінних
Відповідно, необхідно якось розуміти: коли потрібно провести синхронізацію між Model і View.
У сучасних фреймворках, типу Angular або Knockout, до цього питання підходять дуже просто: вішають слухачі на різні події від елемента, якому необхідне динамічне зв'язування даних.
Наприклад, для text input вішається слухач на подію keyup.
Для button - click
І т. д.
Всередині обробника відбувається читання нових даних і потім запускається механізм синхронізації оних з Model.
Ось, власне, і вся історія.
До речі, якщо ви використовуєте Angular, то, швидше за все, вам дуже часто доводиться вдаватися до використання таких речей, як сервіс $ timeout...
Якщо ви використовуєте $ timeout на автоматизмі, тому що так написано десь на stack overflow, але не розумієте його суті, то знайте, що $ timeout чекає, поки закінчиться поточний $ digest-цикл, потім виконує код, який ви йому передали, і потім знову запускає $ digest-цикл. Саме так і досягається оновлення даних, якщо воно було ініційоване не з нутрощів Angular.
Що таке $ digest-цикл?
В AngularJS це якраз і є процес синхронізації значень між Model і View.
І, як обіцяв, посилання на Gist, в якому реалізовано найпростіше динамічне пов'язування даних.
У декількох словах:
- вибираємо всі елементи, у яких є атрибут data-bind
- реєструємо ці елементи як слухачі змін моделі
- вішаємо на document загальний обробник, який буде виробляти синхронізацію між View і Model
Дякую за увагу.






