Vue шаг за шагом. CRUD. Пример#3


12.03.2020

CRUD

В этом примере освоим работу с данными используя подход CRUD (создание (create), чтение (read), обновление (update), удаление (delete)).

Именно понимание основного замысла этого подхода облегчит в будущем разработку и поддержку больших и сложных приложений. В данном примере мы создадим четыре отдельных метода для работы с данными. Каким бы сложным не казалось приложение или структура данных, можно обойтись этими четырьмя методами. Мало того, если backend для любой сущьности будет реализовывать все 4 метода, то frontend сможет реализовать интерфейс любой сложности и любого вида. Крайне желательно чтобы стандарт работы и формат выдачи данных на backend-е не менялся от одной сущьности к другой и выдерживался стандарт. В этом случае Вы сможете создать стандартные компоненты для работы с данными (что и будет продемонстрировано в следующих примерах). В реальной жизни, долгоиграющие проекты страдают болезнью, которую я называю «наслоение исторических слоев». Приходят новые технологии, backend состоит из разных составных частей, backend пишут разные люди/группы, и получается что могут быть совсем не похожие форматы данных. И если здесь не будет стандартизации, это все придется разгребать фронтенду. И мы будем строить такую структуру приложения, чтобы оно в любом случае смогло.

В этом примере реализован подход CRUD, но при этом не выполняются никакие http запросы. CRUD - это подход который применим для работы с любым хранилищем данных. И основная его иде в том, что для работы с любой сущностю достаточно всего 4 метода. Соответственно backend дожен реализовывать эти 4 метода.

Например. Пользователь на сайте заполняет и отправляет форму заказа. При создании заказа выполняется метод "Create". Создается новый заказ. Скорее всего в базе данных создается новая запись. Далее менеджер ставит отметку "Заказ принят". Для изменения статуса заказа выполняется метод "Update", ему передаются данные какие именно данные обновить. Далее кто-то из работников ставит отметку "Заказ передан на обработку / сборку / отправку". Для изменения статуса заказа (и других данных заказа) выполняется один и тот же метод "Update". Разница только в том, какие данные ему передаются. И если Вам в голову придет идея, что можно сделать отдельные роуты на бекенде для обновления статуса заказа типа "order_update_sattus, order_set_done" и так далее, то это не есть правильно. Все обновления должны выполнятся через один метод "Update". Порождение множества путей для обновления данных приводит к путанице, потенциальным ошибкам, и сложностям при обновлении структуры данных.

В будущем CRUD - методы будут изменять данные на backend-е, поэтому назовем их create_back, read_back, update_back, delete_back. Обратите внимание, что эти методы будут отправлять запрос на сервер (backend) и уже после получения от него ответ, выполнять те или иные действия в зависимости от ответа. Но эти методы не должны изменять данные во frontend напрямую. Они должны будут только отправлять запрос на сервер, а после получения ответа вызвать заданную callback функцию. Все остальное не их забота. Разделение полномочий — это основа удачной структуры построения прилодения.

Поскольку для выполнения запроса серверу требуется некоторое время, мы создадим методы, которые будут отправлять запрос на backend и в случае успеха вызывать одну функцию callback, а в случае неудачи - другую.

Поскольку на данный момент отсутствует реальный back-end, данные пока будут хранитсяи в localstorage. Мы пока не сможем проверить все нюансы работы с back-end, с учетом всех временных задержек, проблемы с доступом, и т.п., (этим мы займемся позже когда сделаем свой backend), но сейчас мы сможем выстроить структуру нашего web - приложения таким образом, чтобы в будущем мы могли легко менять методы работы с backend - ом.

Для того, чтобы заполнить Localstorage исходными данными, в примере есть свециальная кнопка "Fill Local Storage".

Пояснения к примеру

В примере напротив каждой записи присутствуют кнопки "R" - read (чтать, при нажатии данные выводятся в консоль), "U"-update (изменить), "D"- delete (удалить). Внизу талицы "C" - create (создать). Можете поиграться с ними у увидеть результат их работы. Изменения сохраняются в Localstorage. Т.е. после перезагрузки страницы все данные останутся. Если Вы захотите восстановить начальные данные - снова нажмите кнопку "Fill Local Storage".

На данном этапе мы создали методы create_back, read_back, update_back, delete_back которые отправляют запрос на изменение/получение данных и вызывают callback при завершении операции. Сами методы не изменяют данных в нашей компоненте, это делают callback функции. Конечно же в данном примере запросы никуда не отравляются, а данные корректируются в локальном хранилище. В будущем мы заменим работу с локальными данными на отправку запроса на backend, а вызов callback-ков перенесем в обработку ответа back-end, но структура останется такой же.

То, что делают callback - функции и как стандартизировать поведение компонент мы рассмотрим в следующем примере. Сейчас важно понять почему мы стараемся отделить функции работы с backend от остального приложения.

Некоторые могут спросить: Зачем делать два callback - callbackOK, callbackError? Можно использовать одну callback-функцию, вызывать ее при любом ответе сервера и передать ей ответ back-end, а она пущай разгребает. Можно и так поступить, но если у нас присутствует хоть малейшая стандартизация, то всякий раз разгребать, скажем данные от ошибок не совсем приятное занятие. Зачем так сделано - увидим в следующих примерах.

Стандартизация

Обратите Ваше внимание на стандартизацию взаимоотношений frontend и backend. Я пришел к следующим требованиям к backend, но Вы можете их переделать под свои условия. Принципиально определиться со стандартом сразу, чтобы не было мучительно больно потом. Давайте разберемся что же получают callback - функции в качестве параметров.

  • create. При успешной операции возвращает {'result': 'OK', 'id': ID}. Где ID - id новой записи. Если backend скажет только "OK, я добавил запись", то frontend - у придется перечитывать весь массив данных, а это может занять очень много времени. Получив id сохраненной запись, frontend сможет перечитать ее и вставить в данные для динамичного отображения.
  • read. Если в качестве параметра передать null - read_back отправит запрос на получения списка данных, соответственно в callback будет передаваться полученный массив [{},{},...{}]. Пример - первоначальная загрузка данных (всего списка 'client'). Если в качестве параметра передать текущую строку (фактически из текущей строк нам нужен только идентификатор записи - id) - read_back отправит запрос на получения одной записи с указанным id. Соответственно, в callback будет передаваться одна запись полученная от back-end-а {}. Пример - нажатие на любую кнопку 'R'. Зачем нам запрашивать от backend- а одну запись если у нас уже есть весь список? Дело в том что в общий список могут быть включены не все поля, а при запросе по конкретной записи с указанным id записи, backend отдаст более детальную информацию с десятком полей, которые при выводе списка будут просто лишние.
  • update. При успешной операции возвращает {'result': 'OK'}
  • delete. При успешной операции возвращает {'result': 'OK'}

Если в результате выполнения запроса произойдет ошибка, то callback - функция получит объект с массивом ошибок.

Обратите внимание, что именно массив, ибо ошибок может быть несколько. Например, пользователь заполнил не все поля формы. Можно конечно отдать только одну, первую попавшуюся ошибку, тогда пользователь будет несколько раз отправлять форму пока не исправит все ошибки. А можно обработать весь массив ошибок и даже вывести подсказки возле неправильно заполненных полей. Разумеется, лучше сразу прийти к какому нибудь стандарту, чтобы упростить себе жизнь обрабатывая ответ полученный от backend-а. Тем не менее, как показывает жизнь, бывают ситуации, когда от стандартов приходиться отступать. Создавая приложение с разделенной ответственностью, я имею в виду, когда отдельные части приложения занимаются узко специализированными вещами, можно создать достаточно гибкое и понятное приложение. Если же все писать в одной куче, например, один метод будет и загружать данные с backend-а, обрабатывать его ответ и что-то делать с данными для отображения, мы получим закостенелый, тяжело развиваемый проект.

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

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

Ссылки

CRUD: https://ru.wikipedia.org/wiki/CRUD

Резюме

В этом примере рассмотрен подход CRUD. Заложена будущая прослойка между backend и остальной частью будущего web-приложения.

В следующем примере

Применение Mixin, создание компонент на основе Mixin — ов.

Смотри также:

Web-dev склерозник
Коментарі:
Додати коментар
Code
* - обов'язкові поля

Архіви