RSS Мои друзья Контакты

KnockOut - наблюдаем за всем и везде

О MVVM патерне, вокруг которого все крутится, уже упоминалось в предыдущей статье. В соответствии патерну, на котором построен фреймворк, Капитан Очевидность КО состоит из 3 основных частей:

  • наблюдаемые свойства и зависимости;
  • декларативные привязки (байндинги);
  • шаблоны (темплейтинг).

Отображение View Model

В качестве ViewModel может быть любой JavaScript объект со свойствами и методами, например

var PersonViewModel = {
    personName: 'Серега',
    personAge:  22
};

Для создания самого простого отображения этой модели достаточно прописать байндинг для любого DOM элемента, например:

Меня зовут <span data-bind="text: personName"></span> и мне <span data-bind="text: personAge"></span> года

Чтобы заставить все это работать достаточно написать (ko - глобальный объект)

ko.applyBindings(PersonViewModel);

В этом случае наш Капитан пройдет по всем элементам DOM, в которых есть атрибут data-bind и выполнит все привязки. Этот атрибут нестандартный для HTML (HTML5 не в счет, он еще не утвержден как стандарт), но это не мешает броузеру работать в нормальном лихорадочном режиме.

Вызов этого скрипта можно поместить в самый низ страницы или же добавить как слушателя на событие DOMContentLoaded, с чем отлично может справится jQuery. Результатом выполнения будет

Меня зовут <span data-bind="text: personName">Серега</span> и мне <span data-bind="text: personAge">22</span> года

Метод applyBindings принимает 2 параметра:

  • обязательный, View Model;
  • необязательный, можно передать DOM элемент, в котором нужно активировать байндинги. Это достаточно удобно когда есть несколько View моделей, так как позволяет ассоциировать каждую из них со своим блоком на странице.

Достаточно просто, не так ли?

Наблюдаемые свойства

Мы уже научились создавать базовую View модель и отображать ее на странице используя байндинги. Но основная изюминка КО - это автоматическое обновление UI, когда происходят определенные изменения в модели. Каким образом Капитан узнает о таких изменениях? Все очевидно! Нужно просто объявить свойства модели как наблюдаемые при помощи метода observable, тогда они становятся объектами, которые умеют сообщать всем подписчикам, что в них произошли изменения. Этот метод принимает единственный необязательный параметр - инициализируемое значение для свойства, если не указать, то будет браться значение из элемента к которому привязано данное свойство.

var PersonViewModel = {
    personName: ko.observable('Серега'),
    personAge:  ko.observable(22)
};

HTML код изменять не нужно. Все будет работать как прежде за исключением того, что при изменении свойства модели, view автоматически обновится.

Поскольку не все броузеры (да-да речь идет именно о IE) поддерживают геттеры/сеттеры в JavaScript, то было решено создать методы-врапперы и устанавливать или получать значения свойств при их помощи. Относительно конкретной модели:

  • прочитать значение можно при помощи обращения к свойству как к методу PersonViewModel.personName() или PersonViewModel.personAge();
  • записывается значение аналогично как и читается, только нужно передать параметр в метод PersonViewModel.personAge(23) - поменяет значение свойства на 23;
  • при вызове наблюдаемых свойств-методов можно пользоваться цепочкой вызовов PersonViewModel.personAge(23).personName()

То есть, когда КО найдет элемент с атрибутом data-bind="text: personName" он подпишет этот элемент на изменения свойства personName и наоборот, при изменении значения текста в DOM элементе об этом будет уведомлено свойство View модели.

Подписаться на изменения свойства также можно вручную при помощи метода subsribe

PersonViewModel.personName.subscribe(function(newValue) {
    alert("Имя человека изменилось на " + newValue);
});

Но в большинстве случаев этого делать не придется, потому что встроенных байндингов достаточно для манипуляции подписками.

По материалам: KnockOut

Добавить комментарий

Комментариев: 0