Статьи

Создайте менеджер контактов с помощью Backbone.js: часть 5

Добро пожаловать обратно в Построение средства просмотра контента с помощью серии Backbone . В первых четырех частях мы рассмотрели почти все основные компоненты, которые поставляются с последней версией Backbone, включая модели, контроллеры, представления и маршрутизаторы.

В этой части руководства мы собираемся подключить наше приложение к веб-серверу, чтобы мы могли хранить наши контакты в базе данных. Мы не будем смотреть на LocalStorage; это популярный способ сохранения данных, которые используются приложениями Backbone, но факт в том, что по этому вопросу уже есть множество отличных учебных пособий.


Нам понадобится веб-сервер и база данных для этой части руководства. Я использую VWD от Microsoft в качестве редактора, который поставляется со встроенным веб-сервером и хорошо работает с MSSQL-сервером, так что это то, что мы будем использовать. По правде говоря, не имеет значения, с каким стеком вы решили пойти.

Установка и настройка любой из этих технологий (VWD и MSSQL-сервер) выходит за рамки этого учебного пособия, но это относительно просто, и есть много хороших руководств.

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

Один столбец, который должен появиться в нашей новой таблице, но который мы не использовали в наших локальных тестовых данных, — это id , который должен быть уникальным для каждой строки в таблице. Для простоты использования вы, вероятно, захотите установить автоматическое увеличение при добавлении данных в таблицу.


Для связи с сервером Backbone предоставляет нам модуль Sync ; это единственный основной модуль, который мы еще не использовали, поэтому его понимание дополнит наши знания основ фреймворка.

Вызов метода sync() приводит к запросу на сервер; по умолчанию предполагается, что используется либо jQuery, либо Zepto, и делегирует запрос тому, кто из них присутствует, для фактического выполнения. Он также предполагает, что интерфейс RESTful ожидает на стороне сервера, поэтому по умолчанию используются методы HTTP POST, PUT, GET, DELETE. Как мы уже видели, Backbone может быть настроен на использование старых методов GET и POST с дополнительными заголовками, которые определяют предполагаемое действие.

Помимо возможности прямого вызова sync() , модели и коллекции также имеют методы, которые можно использовать для связи с сервером; модели имеют методы destroy() , fetch() , parse() и save() , а коллекции имеют fetch() и parse() . Методы destroy() fetch() и sync() все откладывают на sync() независимо от того, используются ли они с моделями или коллекциями. Метод parse() , вызываемый автоматически всякий раз, когда данные возвращаются сервером, по умолчанию представляет собой простой запрет, который просто возвращает ответ от сервера, но его можно переопределить, если мы хотим предварительно обработать ответ перед его использованием.


Способ загрузки данных модели на страницу зависит от используемой серверной технологии.

В документации Backbone для метода fetch() (из коллекции) говорится, что этот метод не следует использовать при начальной загрузке страницы для запроса требуемых моделей с сервера. Далее в разделе часто задаваемых вопросов уточняется, что на странице должны быть загружены необходимые модули для загрузки страницы, чтобы избежать первоначального запроса AJAX.

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

Способ загрузки данных модели на страницу зависит от используемой серверной технологии. Мы собираемся использовать .net в этом примере, поэтому одним из способов будет динамическое создание элемента <script> содержащего необходимые данные модели, и вставка его на страницу. Чтобы сделать это, нам нужно вместо этого преобразовать наш файл index.html в index.aspx (нам также понадобится index.aspx.cs индекс index.aspx.cs или файл класса). Но при этом возникает новая проблема.


Мы можем поднять пример «стиля усов» прямо со страницы документации Underscore.

Проблема с шаблонами Underscore заключается в том, что они используют <%= для указания заполнителей в шаблоне, которые заменяются фактическими данными при использовании шаблона. Это тот же синтаксис, который используют страницы ASPX для запуска динамического кода .Net внутри тегов HTML. Шаблоны Underscore, которые мы использовали в этом примере, до сих пор препятствуют правильной работе страницы ASPX и вместо этого отображают ошибку сервера.

К счастью, есть несколько способов обойти эту проблему, самый простой способ — изменить синтаксис, используемый для указания заполнителей, используемых в шаблонах. Underscore предоставляет свойство templateSettings для этой цели, что позволяет нам легко указать регулярное выражение, используемое для соответствия символам, которые мы хотим использовать. Мы можем поднять пример «стиля усов» прямо со страницы документации Underscore; в начале нашего файла app.js (внутри самой внешней функции) мы можем просто добавить следующий код:

1
2
3
_.templateSettings = {
    interpolate: /\{\{(.+?)\}\}/g
};

Все, что это делает, это предоставляет новое регулярное выражение для метода interpolate , что позволяет нам использовать альтернативный синтаксис {{ property }} вместо <%= property %> . На этом этапе мы также должны пройти через шаблоны и изменить все оригинальные теги шаблонов, чтобы использовать новый синтаксис.

Хотя это не то, что мы использовали в наших шаблонах до сих пор, есть также дополнительные символы, которые Underscore может использовать. Мы можем оценить JavaScript, используя <% и можем избежать данных, используя <%- . Если мы хотим использовать их в наших шаблонах и заменили свойство interpolate , нам также следует настроить свойства evaluate и escape Underscore.


Теперь мы можем подумать о доставке данных модели, которые хранятся в базе данных, на нашу страницу, когда страница первоначально отображается. Мы можем легко сделать это, добавив простой метод в файл класса для нашей страницы ASPX, который считывает записи из базы данных и создает список объектов, где каждый объект представляет один контакт. Затем мы можем сериализовать список в массив JavaScript и вставить его на страницу. Поскольку массив имеет тот же формат, что и фиктивный массив, который мы использовали в первых четырех частях этого урока, нам не придется изменять наш код переднего плана.

В качестве заполнителя для массива мы можем просто добавить новый элемент <script> в тело страницы непосредственно перед ссылкой на app.js , который вызывает метод в коде:

1
2
3
<script>
    var contacts = <%= getData() %>
</script>

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

На этом этапе мы должны быть в состоянии удалить массив контактов, содержащий наши фиктивные данные, из app.js , запустить страницу (через встроенный веб-сервер WVD или IIS) и увидеть точно такую ​​же страницу с почти такими же функциями. , как мы видели в конце части 4. Yay!


В этом примере я использовал ASMX-файл .net 4.0 для обработки запросов от внешнего интерфейса. Чтобы emulateHTTP emulateJSON видеть отправленные ему данные, нам нужно настроить свойства магистрали emulateHTTP и emulateJSON . Добавьте следующие строки кода непосредственно после того, где мы изменили синтаксис шаблона Underscore:

1
2
Backbone.emulateHTTP = true;
Backbone.emulateJSON = true;

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

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

Логика для выполнения всех этих действий во внешнем интерфейсе уже существует, но теперь, когда задействован сервер, поведение страницы уже изменилось. Хотя страница будет отображаться так же, как и раньше, если мы попытаемся удалить контакт, Backbone выдаст ошибку, сообщающую, что URL не был определен. Причина этого в том, что мы использовали метод destroy() методе deleteContact() нашего класса ContactView .

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

1
2
3
url: function () {
    return «/ContactManager.asmx/ManageContact?id=» + this.get(«id»);
}

Мы указываем функцию в качестве значения свойства url , которое возвращает URL, который должен использоваться для выполнения запросов. В этом примере мы можем использовать файл веб-службы asmx для обработки запросов. Мы также добавляем имя нашего веб-метода ( ManageContact ) и добавляем id модели в качестве параметра строки запроса.

Теперь, если мы удаляем один из контактов при запуске страницы, в веб-службу поступает запрос POST. Заголовок X-HTTP-Method-Override добавляется к запросу, который указывает, что предполагаемый метод HTTP был DELETE . Мы можем использовать это в логике нашего веб-сервиса, чтобы определить, какое действие предпринять с базой данных.

Затем мы можем обновить метод saveEdits() класса ContactView чтобы он уведомлял веб-службу об изменении контакта; измените строку кода, которая использует метод set() чтобы она выглядела следующим образом:

1
this.model.set(formData).save();

Все, что мы делаем, это связываем метод save() методом set() . Метод save() делегирует метод sync() который отправляет POST-запрос на сервер. Как и прежде, id модели отправляется в виде строки запроса, а X-HTTP-Method-Override используется для указания предполагаемого метода PUT. На этот раз, однако, заголовок Content-Type установлен на application/x-www-form-urlencoded (если мы не настроили свойство emulateJSON это было бы application/json ), и данные модели отправляются как данные формы, которые мы можем использовать для внесения любых необходимых изменений.

Все, что осталось сделать на addContact() интерфейсе, это обновить метод addContact() класса DirectoryView . Ранее в этом методе у нас был оператор if, который проверял тип добавляемой модели, чтобы увидеть, нужно ли обновить меню выбора. Теперь мы должны изменить это утверждение if, чтобы оно выглядело следующим образом:

1
2
3
4
5
if (_.indexOf(this.getTypes(), formData.type) === -1) {
    this.$el.find(«#filter»).find(«select»).remove().end().append(this.createSelect());
}
 
this.collection.create(formData);

Мы сократили оператор if , чтобы удалить условие else , сделав код немного более аккуратным. Мы также удалили метод add() и добавили вместо него метод create() . Метод create() фактически автоматически добавляет новую модель в коллекцию без необходимости создания нами нового экземпляра класса нашей модели вручную, а также отправляет запрос на сервер, снова делегируя sync() .

На этот раз не нужно устанавливать заголовок X-HTTP-Method-Override , потому что POST — это метод, который мы использовали бы, если бы запрос в любом случае был сделан к интерфейсу RESTful. Как и в случае с методом save() , данные модели, передаваемые методу create() доставляются на сервер в виде данных формы.

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


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

Мы увидели, как Backbone по умолчанию отправляет запросы RESTful на указанный URL-адрес и как мы можем настроить его для работы с устаревшими серверами, которые не работают по принципам REST. Мы также рассмотрели некоторые методы, которые делегируют sync() для связи с сервером. В частности, мы рассмотрели методы remove() , save() и create() и посмотрели, что и как отправляется на сервер.

Мы также рассмотрели, как легко изменить символы, используемые Underscore для интерполяции данных в шаблон. На этом завершается учебник Contact Manager; В то время как есть еще много функций, которые мы могли бы добавить в приложение, теперь мы рассмотрели основы того, что нужно для создания полнофункционального приложения с использованием превосходного Backbone.js. Спасибо за прочтение.