Статьи

KnockoutJS: введение

Появление сложных веб-приложений, таких как GMail, породило целую армию фреймворков Javascript. Эти платформы позволяют вам, в основном, создавать клиентское приложение в вашем веб-приложении. Такие термины, как «MVC» и другие шаблоны проектирования, когда-то сохраненные только для серверной части сети, теперь применяются только к клиентским битам вашего кода. В наши дни наиболее популярными фреймворками являются http://backbonejs.org , http://emberjs.com и http://knockoutjs.com . В этой статье мы рассмотрим последний.

(ПРИМЕЧАНИЕ. Мне потребовались все силы воли, чтобы не озаглавить эту статью «Мама сказала, нокаутируй!» Или что-то подобное. На самом деле, моей силе воли требовалась помощь наркотиков.)

Knockout использует подход Model-View-View-Model (MVVM) к архитектуре приложения. MVVM — это архитектурный шаблон, который имеет (некоторые из) свои корни в Microsoft и их Windows Presentation Foundation / Silverlight / Failed Попытка сделать ASP.NET Web Forms пригодными для использования. Честно говоря, я избегал Knockout из-за этих корней, и я предполагаю, что многие разработчики тоже. Только когда я унаследовал приложение, использующее Knockout, я был вынужден узнать об этом.

Еще раз, я был приятно удивлен, узнав, что мой необоснованный уклон разработчика был очень неправильным.

По крайней мере, это не MVC

Глядя на домашнюю страницу Knockout , ключевые понятия, которые она перечисляет:

  • Деклятивные привязки
  • Автоматическое обновление интерфейса
  • Отслеживание зависимости
  • Шаблонирование

Я не собираюсь проходить через каждый из них, так как у вас есть одинаковый доступ к их сайту. Я скажу, что я думаю, это означает, в двух словах. На мой взгляд, сила Knockout заключается в привязке данных. Если вы никогда не использовали каркас, который связывает пользовательский интерфейс с моделью (модель представления, в данном случае), основная идея заключается в том, что любые изменения этой модели немедленно отражаются в представлении / интерфейсе пользователя. Adobe Flex — это, на мой взгляд, самая известная инфраструктура привязки данных. Привязка данных чрезвычайно мощна, особенно если у вас есть части вашей модели, разбросанные по пользовательскому интерфейсу. Обновление значения в одном месте и изменение 10 элементов пользовательского интерфейса в результате вызовет улыбку на любом троллфейсе.

Привязка данных — самый сладкий соус, который предлагает Knockout, но это не только. Шаблонирование очень мощное, и вы можете использовать любую библиотеку шаблонов javascript, которая вам нравится (шаблоны jQuery, усы и т. Д.). Knockout также расширяем, предоставляя инфраструктуру плагинов, которой мы воспользуемся в демонстрационном приложении, которое я собрал, чтобы показать Knockout в действии.

Лик это, Лик это хорошо

Демонстрационное приложение — это простое, но довольно отвратительное приложение под названием LinkLicker. Идея в том, что ссылки отправляются, а вы выбираете те, которые вам нравятся Да, мне 4 года.

Серверная часть этого приложения является приложением Rails и не имеет значения. Вашему серверному приложению просто нужно выплюнуть JSON, так что это может быть Sinatra или Rails, Куба или что угодно. Я хочу рассказать вам подробности веб-приложения, но они есть в репозитории github, если вы просто должны знать .

Приложение показывает форму, которая позволяет отправлять ссылки, список отправленных ссылок и список ссылок, которые были вылизаны текущим пользователем. Когда ссылка вылизана, ее значок меняется. Это, я уверен, следующий FacebookTwitter.

Настроить

Для этого вам понадобится код Knockout, доступный в вашем веб-приложении. Я поместил мой в каталог vendor вместе с наиболее часто используемым плагином Knockout. Этот плагин является плагином Knockout Mapping , и он берет на себя всю тяжелую работу по преобразованию JSON с сервера в объекты javascript на клиенте. Примечание: я не буду подробно описывать плагин Mapping в этой статье, но важный момент заключается в том, что он создает наблюдаемые из всех наших свойств JSON при отображении объектов. Вы увидите, что наблюдаемые в ближайшее время.

Структурно мне нравится помещать каждый «модельный» класс в отдельный файл на клиенте. LinkLicker действительно имеет только одну модель: Link. Мне также нравится иметь глобальный класс, представляющий мое приложение, которое я безоговорочно называю App. Окончательная структура каталога для javascript выглядит следующим образом:

UI

Пользовательский интерфейс для LinkLicker был в значительной степени обусловлен моим желанием сделать как можно меньше, в то же время продвигая концепции Knockout. Как я уже упоминал выше, есть форма, а также три списка ссылок. Три списка: «Все ссылки», «Новые» (смысловые, неотмеченные) и «зализанные» ссылки. Как вы, возможно, догадались, ссылка может находиться в нескольких списках одновременно. Скриншот пользовательского интерфейса ниже:

начальная загрузка

Начальная загрузка LickLinker состоит из привязки к форме и создания наших трех списков. Мы сделаем все эти свойства в нашем приложении. Легкие вещи.

var App = function() { this.newLink = ko.observable(new Link()); this.mylinks = ko.observableArray(); this.lickedLinks = ko.observableArray(); this.allLinks = ko.observableArray(); }; 

Вы, вероятно, задаетесь вопросом, каково все это наблюдаемое безумие. Когда вы делаете свойство наблюдаемым, оно становится сверхмощным уведомителем об изменениях этого свойства. Knockout будет отслеживать (насколько это возможно, и он довольно хорош в этом) вещи, которые заинтересованы в вашей собственности, и сообщать, когда она изменится. Документы Observables на сайте Knockout великолепны, и есть также интерактивные учебники, которые можно использовать.

Короче говоря, и если вы можете подумать о будущем, когда мы свяжем наш пользовательский интерфейс (форму) с newLink, он будет уведомлять нашу форму изменений и наоборот.

Другие три свойства являются наблюдаемыми массивами . Концептуально они точно такие же, как наблюдаемые, за исключением того, что они работают над коллекцией. ObservableArray будет отслеживать, какие объекты находятся в массиве, и у него есть много вспомогательных методов для добавления и удаления этих объектов. Вы можете легко вставлять или помещать элементы в массив observableArray, нарезать его, получать его длину, инвертировать его и многие другие методы, которые вы ожидаете.

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

Модель

Модель для LinkLicker — это просто ссылка, и она имеет 3 свойства: url, description и lickedByCurrentUser.

Форма

Нокаут это все о привязке данных, помните? Таким образом, мы можем связать новую ссылку с формой, а затем, когда пользователь вводит данные, он заполняет эту новую связанную ссылку. В приведенном выше фрагменте кода мы создаем наше свойство newLink как наблюдаемое. Теперь, чтобы связать это с формой:

 <form id="create_form" class="one-third column alpha" data-bind="submit: createNewLink"><!-- ko with: newLink --> <label for="link_url">Link:</label> <input id="link_url" type="text" name="linkhttps%3A%2F%2Fwww.sitepoint.com" data-bind="value: url" /> <label for="description">Description:</label> <input id="link_description" type="text" name="link[description]" data-bind="value: description" /> <!-- /ko --> <input type="submit" value="Add" /></form> 

В приведенном выше фрагменте, сфокусируйтесь на <!-- ko with: newLink --> строки <!-- ko with: newLink --> . Knockout предлагает несколько различных способов привязки частей DOM к модели представления. В этом примере используются «безконтейнерные привязки», что означает, что он не создает элемент DOM для этого объявления.

Другой способ сделать это — создать элемент DOM (например, div ) и добавить атрибут data-bind указывающий шаблон. На сайте Knockout есть множество примеров, если вы не уверены.

Эта ko with: newLink говорит Knockout найти свойство newLink того, с чем связано это представление, и охватить все, что находится внутри блока, с ним. Это должно быть немного понятнее, если вы посмотрите на input теги. Каждый входной тег имеет атрибут data-bind который связывает значение этого ввода со свойством newLink.

Связи Связывают

С нашим пользовательским интерфейсом нам нужен механизм, чтобы связать его с нашей моделью представления. В этом приложении модель представления является нашим глобальным классом приложения на клиенте. Приложение привязано к представлению при загрузке страницы, как показано здесь:

 $(function(){ App.globalApp = new App(); ko.applyBindings(App.globalApp); App.globalApp.loadLinks(); }); 

Очень просто.

Фильтрация списка может быть выполнена путем создания двух «вычисляемых» (ранее зависимых от наблюдаемых объектов). Здесь, позвольте мне показать вам:

 this.allLinks = ko.observableArray(); this.lickedLinks = ko.computed(function() { return this.allLinks().filter(function(link) { return link.isLicked(); }); }, this); this.newLinks = ko.computed(function() { return this.allLinks().filter(function(link) { return !link.isLicked(); }); }, this); 

computed является наблюдаемой, которая зависит от значений других наблюдаемых. Вы можете видеть, что мы фильтруем allLinks observableArray на основе значения isLicked () для каждой ссылки. Вторым аргументом для вычисляемого ( this ) является контекст для привязки функции.

Компьютеры чрезвычайно полезны, и вы обнаружите, что используете их повсюду.

Расширение KnockoutJS

Хотя у Knockout есть много-много привязок, которые вы можете использовать, таких как text, html, css, visible, вы найдете случаи, когда требуется новая привязка. Написание пользовательского связывания очень просто. В качестве примера я собираюсь написать hidden привязку, которая противоположна visible привязке. Это ниже:

 ko.bindingHandlers.hidden = { update: function(element, valueAccessor){ var value = ko.utils.unwrapObservable(valueAccessor()); ko.bindingHandlers.visible.update(element, function() { return !value; }); } }; 

В привязке я беру значение привязываемого элемента, а затем передаю его существующей visible привязке. Результат отменяется и возвращается.

Очевидно, что это тривиальная привязка, но вы можете получить очень сложную при необходимости. Например, Google покажет вам привязки для элементов пользовательского интерфейса jQuery, а также тысячи других пользовательских привязок, созданных сообществом.

Мама сказала, заверни это!

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

Помните, что весь источник LinkLicker вы можете просматривать, использовать, высмеивать, что угодно на github .

Если у вас есть вопросы по LinkLicker или Knockout, напишите мне в комментариях. Спасибо за прочтение!