Предыдущий ролик Следующий ролик  

Видео урок: Model binding with Knockout

Основы ASP.NET MVC 5

В этом видео я познакомлю вас с некоторыми базовыми понятиями Knockout. Knockout - это первоклассная библиотека JavaScript, использующая паттерн Model-View-View Model (MVVM) для упрощения синхронизации всех элементов на стороне клиента, а также синхронизации их свойств. Для начала поговорим немного о паттерне Model-View-View Model, или MVVM, и о том, какое значение он имеет, если ASP.NET MVC используется вместе с Knockout. MVVM расшифровывается как "Model-View-View Model" (Модель-Представление-Модель представления), довольно запутанная аббревиатура. Но обратите внимание на те дефисы, которые разделяют эти три компонента: Модель, Представление и Модель представления. Приведем краткое пояснение. Модель - это та же самая модель, о которой мы говорили во время обсуждения архитектурного паттерна MVC. Это класс, имеющий дело с сохраненными данными нашего приложения. Представление - то же самое представление, о котором мы говорили все это время. С другой стороны, модель представления - это отображение данных, с которыми мы будем работать на стороне клиента, в данном пользовательском интерфейсе и, возможно, некоторых операций, которые можно определить для этих данных в пользовательском интерфейсе.

В Knockout большинство элементов модели представления будет отображаться с помощью так называемых "наблюдаемых объектов" (observables). Это объекты, которые в случае внесения в них каких-то изменений способны уведомлять об этом другие объекты, с тем чтобы эти другие объекты могли соответствующим образом обновить свое собственное состояние. Еще один вариант - за этими объектами могут наблюдать другие, зависящие от них объекты. В качестве простого примера представьте себе текстовую область для сообщения Twitter'а, или твита, которое может содержать не более 140 символов. Чаще всего рядом с такой областью отображается динамически обновляемое сообщение, в котором указывается количество оставшихся символов в тот момент, когда пользователь вводит текст твита в режиме реального времени.

В Knockout реализовать это довольно легко. И перед тем как перейти к более важному примеру, в котором создается дополнительная функциональность для нашей системы банкоматов, я покажу вам аналогичный простой пример с помощью нашей контактной формы. Первое, что нужно сделать, - получить скрипт Knockout с помощью NuGet. Нажмите правой кнопкой мыши на папке References, выберите пункт "Управление пакетами NuGet", а затем найдите Knockout.js и установите ее.

Перетащим ее в секцию script, а затем ниже создадим еще один элемент script, в котором определим нашу модель представления. Модель представления будет задаваться в виде функции. Назовем ее ContactViewModel. Чтобы не беспокоиться об области действия этой функции, просто объявляйте переменную, подобную self, и присваивайте ей значение this. В первую очередь я объявлю свойство message. Через некоторое время я привяжу его к сообщению в текстовой области.

Это свойство создается с помощью ko.observable. Если нужно проинициализировать свойство каким-то значением, то можно передать его сюда вместо пустой строки, которую я использую сейчас. Далее настроим сообщение, в котором будет указываться количество оставшихся символов. Допустим, у элемента textarea есть атрибут maxLength, равный 150. Опять же, было бы здорово сообщить это значение пользователю, а еще лучше, если по мере того, как он будет набирать сообщение, вы сможете сообщать ему, сколько еще символов он может ввести.

Итак, определим еще одно свойство модели представления под названием charactersRemaining. Это экземпляр так называемого вычисляемого, наблюдаемого объекта, потому что конструировать его мы будем динамически на основании текущей длины сообщения. Вот так выглядит конструктор: ko.computed. Затем мы передаем в него функцию, предназначенную для формирования значения свойства. Эта функция будет возвращать значение, вычисляемое по формуле: 150 - self.message().length. Обратите внимание, для того чтобы получить или задать значение свойства message, нужно вызвать его как функцию, подобно тому, как мы использовали val в jQuery. Использование self в этом месте вполне оправданно, поскольку применение this внутри этой функции привело бы к неправильному контексту.

Хотя мы могли бы передать this в качестве второго параметра после безымянной функции, и тогда бы все заработало. Итак, осталось выполнить еще несколько настроек. Во-первых, нужно привязать наблюдаемое сообщение к значению текстовой области. Делается это с помощью атрибута data-bind. Просто присвоим ему значение "value:message". Далее нам нужен элемент, к которому мы привяжем свойство charactersRemaining. Для этого можно воспользоваться тегом span.

Поскольку в этом случае мы не имеем дело с входным значением, которое пользователь может отредактировать, воспользуемся атрибутом dash-bind со значением "text:charactersRemaining". Наконец, для активации связывания нужно вызвать ko.applyBindings и передать в него экземпляр ContactViewModel. Сохраним изменения и обновим страницу Contact. Все это было у нас и раньше. Введем тестовое сообщение. Как видите, ничего впечатляющего в этом нет, но если выйти из текстовой области, то обновится количество оставшихся символов.

А все потому, что по умолчанию наблюдаемое сообщение оповещает пользователей об изменении значения, и обычно это делается после выхода из соответствующего поля. Но мы можем изменить это поведение, добавив еще одно свойство к атрибуту data-bind текстовой области под названием valueUpdate. По умолчанию используется значение "change", но можно использовать также "input", "key up", "key press" и "after key down". Обычно я выбираю вариант "after key down". Но надежнее использовать вариант "input", если браузер пользователя достаточно современен и поддерживает HTML5-событие input и даже может распознавать вставку в текстовую область.

Давайте протестируем наш код и предоставим пользователю более подробную информацию о появляющейся цифре, добавив после нее фразу "characters remaining" (символов осталось). Сохраним изменения и обновим страницу. Вот теперь получаем желаемый результат, даже если будем вырезать и вставлять текст. Мы вкратце рассмотрели возможности Knockout и увидели, с какой легкостью мы можем настраивать динамическое поведение и синхронизировать объекты. В следующем видео мы с помощью Knockout создадим простую сетку, разбитую на страницы, для выписки по текущему счету.