[Перевод] Веб-приложение на Node и Vue, часть 5: завершение работы над проектом17.01.2018 11:48
Перед вами перевод пятой части руководства по разработке веб-решений на базе Node.js, Vue.js и MongoDB. В первой, второй, третьей и четвёртой частях мы рассказывали о поэтапном создании клиентской и серверной частей приложения Budget Manager. Те, кому не терпится увидеть в действии то, что в итоге получилось у автора этого материала, могут заглянуть сюда. Кроме того, вот GitHub-репозиторий проекта. Если вы — из тех, кто ценит строгую типизацию, то здесь и здесь находятся результаты переноса Budget Manager на TypeScript.
Сегодня работа над этим учебным проектом завершится. А именно, в данном материале пойдёт речь о разработке страниц по добавлению в систему записей о новых клиентах и финансовых документах, а также о создании механизмов для редактирования этих данных. Здесь же мы рассмотрим некоторые улучшения API и доведём Budget Manager до рабочего состояния.
Доработка API
Для начала перейдём в папку models и откроем файл budget.js. Добавим в него поле description для модели:
description: {
type: String,
required: true
},
Теперь перейдём в папку app/api и откроем файл budget.js, который находится в ней. Тут мы собираемся отредактировать функцию сохранения данных, store, для того, чтобы новые документы обрабатывались правильно, добавить функцию edit, которая позволит редактировать документы, добавить функцию remove, которая нужна для удаления документов, и добавить функцию getByState, которая позволит фильтровать документы. Здесь приведён полный код файла. Для того, чтобы его просмотреть, разверните соответствующий блок. В дальнейшем большие фрагменты кода будут оформлены так же.
Здесь мы импортировали и определили компонент Create и назначили его компонентом маршрута Home (сам компонент создадим ниже).
Создание новых компонентов
▍Компонент Create
Начнём с компонента Create. Перейдём в папку components/pages и создадим там новый файл Create.vue.
Исходный код
Первый именованный слот — budget-creation. Он представляет компонент, который мы будем использовать для создания новых финансовых документов. Он будет виден только в том случае, когда свойство budgetCreation установлено в значение true, а editPage — в значение false, мы передаём ему всех наших клиентов и метод saveBudget.
Второй именованный слот — client-creation. Это — компонент, используемый для создания новых клиентов. Он будет видимым лишь в том случае, когда свойство budgetCreation установлено в false, и editPage так же имеет значение false. Сюда мы передаём метод saveClient.
Третий именованный слот — budget-edit. Это — компонент, который применяется для редактирования выбранного документа. Видим он только тогда, когда свойства budgetEdit и editPage установлены в true. Сюда мы передаём всех клиентов, выбранный финансовый документ и метод fixClientNameAndUpdate.
И, наконец здесь имеется, последний именованный слот, который используется для редактирования информации о клиентах. Он будет видим тогда, когда свойство budgetEdit установлено в false, а editPage — в true. Ему мы передаём выбранного клиента и метод updateClient.
▍Компонент BudgetCreation
Разработаем компонент, который используется для создания новых финансовых документов. Перейдём в папку components и создадим в ней новую папку, дав ей имя Creation. В этой папке создадим файл компонента BudgetCreation.vue.
Компонент это довольно большой, разберём его поэтапно, начиная с шаблона.
Тут мы сначала добавляем в шаблон элемент v-select для установки состояния документа, затем — v-select для выбора клиента, который нам нужен. Далее, у нас имеется поле v-text-field для ввода заголовка документа и v-text-field для вывода описания.
Затем мы перебираем элементы budget.items, что даёт нам возможность добавлять элементы в документ и удалять их из него. Здесь же имеется красная кнопка, которая позволяет вызывать функцию removeItem, передавая ей элемент, который нужно удалить.
Далее, здесь есть три поля v-text-fields, предназначенные, соответственно, для названия товара, цены за единицу и количества.
В конце ряда имеется простой элемент span, в котором выводится промежуточный итог по строке, subtotal, представляющий собой произведение количества и цены товара.
Ниже списка товаров имеется ещё три элемента. Это — синяя кнопка, которая используется для добавления новых элементов путём вызова функции addItem, элемент span, который показывает общую стоимость всех товаров, которые имеются в документе (сумма показателей subtotal всех элементов), и зелёная кнопка, которая используется для сохранения документа в базу данных путём вызова функции saveBudget с передачей ей, в качестве параметра, документа, который мы хотим сохранить.
Скрипт компонента BudgetCreation
Вот код, который приводит компонент BudgetCreation в действие
В этом коде мы сначала получаем два свойства — clients и saveBudget. Источник этих свойств — компонент Home.
Затем мы определяем объект и массив, играющие роль данных. Объект имеет имя budget. Он используется для создания документа, мы можем добавлять в него значения и сохранять его в базе данных. У этого объекта есть свойства title (заголовок), description (описание), state (состояние, по умолчанию установленное в значение writing), client (клиент), total_price (общая стоимость по документу), и массив товаров items. У товаров имеются свойства title (название), quantity (количество), price (цена) и subtotal (промежуточный итог).
Здесь же определён массив состояний документа, states. Его значения используют для установки состояния документа. Вот эти состояния: writing, editing, pending, approved, denied и waiting.
Ниже, после описания структур данных, имеется пара методов: addItem (для добавления товаров) и removeItem (для их удаления).
Каждый раз, когда мы щёлкаем по синей кнопке, вызывается метод addItem, который добавляет элементы в массив items, находящийся внутри объекта budget.
Метод removeItem выполняет обратное действие. А именно — при щелчке по красной кнопке заданный элемент удаляется из массива items.
Стили компонента BudgetCreation
Вот стили для рассматриваемого компонента
Теперь рассмотрим следующий компонент.
▍Компонент ClientCreation
Этот компонент, по сути, является упрощённой версией только что рассмотренного компонента BudgetCreation. Мы так же, как сделано выше, рассмотрим его по частям. Если вы разобрались с устройством компонента BudgetCreation, вы без труда поймёте и принципы работы компонента ClientCreation.
Шаблон компонента ClientCreation
Save
Скрипт компонента ClientCreation
Стили компонента ClientCreation
Теперь пришла очередь компонента BudgetEdit.
▍Компонент BudgetEdit
Этот компонент, по сути, является модифицированной версией уже рассмотренного компонента BudgetCreation. Рассмотрим его составные части.
Единственное различие шаблонов компонентов BudgetEdit и BudgetCreation заключается в кнопке сохранения изменений и в связанной с ней логике. А именно, в BudgetCreation на ней написано Save, она вызывает метод saveBudget. В BudgetEdit эта кнопка несёт на себе надпись Update и вызывает метод fixClientNameAndUpdate.
Скрипт компонента BudgetCreation
Здесь всё начинается с получения трёх свойств. Это — clients, fixClientNameAndUpdate и selectedBudget. Данные тут те же самые, что и в компоненте BudgetCreation. А именно, тут имеется объект Budget и массив states.
Далее, здесь можно видеть обработчик события жизненного цикла компонента mounted, в котором мы вызываем метод parseBudget, о котором поговорим ниже. И, наконец, здесь есть объект methods, в котором присутствуют уже знакомые вам по компоненту BudgetCreation методы addItem и removeItem, а также новый метод parseBudget. Этот метод используется для того, чтобы установить значение объекта budget в то, которое передано в свойстве selectedBudget, но мы, кроме того, используем его для подсчёта промежуточных итогов по товарам документа и общей суммы по документу.
Стиль компонента BudgetCreation
▍Компонент ClientEdit
Этот компонент, по аналогии с только что рассмотренным, похож на соответствующий компонент, используемый для создания клиентов — ClientCreation. Главное отличие заключается в том, что тут вместо метода saveClient используется метод updateClient. Рассмотрим устройство компонента ClientEdit.
Шаблон компонента ClientEdit
Update
Скрипт компонента ClientEdit
Стиль компонента ClientEdit
На этом мы завершаем создание новых компонентов и переходим к работе с компонентами, которые уже были в системе.
Доработка существующих компонентов
Теперь осталось лишь внести некоторые изменения в существующие компоненты и приложение будет готово к работе.
Начнём с компонента ListBody.
▍Компонент ListBody
Шаблон компонента ListBody
Напомним, что код этого компонента хранится в файле ListBody.vue
Исходный код
{{ info }}
mode_editdelete_forever
{{ info }}
mode_editdelete_forever
В этом компоненте надо выполнить буквально пару изменений и дополнений. Так, сначала добавим новое условие в конструкцию v-if блока md-list-item:
parsedBudgets === null
Кроме того, мы уберём первую кнопку, которую использовали для вывода документа, так как она нам больше не нужна из-за того, что увидеть документ можно, нажав на кнопку редактирования.
Тут мы добавили метод getItemAndEdit к новой первой кнопке и метод deleteItem к последней кнопке, передавая этому методу элемент, данные и переменную budgetsVisible в качестве параметров.
Ниже всего этого имеется блок md-item-list, который мы используем для вывода отфильтрованного после поиска списка документов.
Скрипт компонента ListBody
В этом компоненте мы получаем множество свойств. Опишем их:
data: это либо список документов, либо список клиентов, но никогда и то и другое.
budgetsVisible: используется для проверки того, просматриваем ли мы список документов или клиентов, может принимать значения true или false.
deleteItem: функция для удаления элемента, которая принимает, в качестве параметра, некий элемент.
getBudget: функция, которую мы используем для загрузки отдельного документа, который планируется редактировать.
getClient: функция, используемая для загрузки карточки отдельного клиента для последующего редактирования.
parsedBudgets: документы, отфильтрованные после выполнения поиска.
В компоненте есть всего один метод, getItemAndEdit. Он принимает, в качестве параметра, элемент, при этом, на основе анализа наличия у элемента свойства, содержащего телефонный номер, принимается решение о том, является ли элемент карточкой клиента или финансовым документом.
Стиль компонента ListBody
Правку кода компонента ListBody мы завершили, займёмся теперь компонентом Header.
▍Компонент Header
Шаблон компонента Header
{{ budgetsVisible ? "Clients" : "Budgets" }}
Sign out
Здесь, в первую очередь, мы меняем свойство v-model поля поиска на searchValue.
Кроме того, мы модифицируем элемент v-select, привязывая к его событию change метод selectState.
Скрипт компонента Header
Тут добавлены два новых свойства — selectState, представляющее собой функцию, и search, которое является строкой. В данных search теперь используется searchValue и приведённый к нижнему регистру массив элементов statusItems.
Стиль компонента Header
С компонентом Header мы разобрались, теперь поработаем с компонентом Home.