Динамическое связывание данных в HTML и JS

Всем доброго времени суток.
Если вы задаетесь одним из следующих вопросов:

  • что такое динамическое связывание данных?
  • как работает связывание данных в 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

3d36366c49594a05b879560b1a0e0368.jpg

Если отбросить формальности, то так оно и есть. Поэтому я и сказал, что грань между 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

Спасибо за внимание.

© Habrahabr.ru