[Назад](./web_03.md) | [К содержанию](../readme.md#введение-в-web-разработку) | [Дальше](./web_05.md) # Vue.js: концепции, криптономикон ## #8 Бизнес логика или детали реализации? > 10 минут * [YouTube](https://www.youtube.com/watch?v=U2ZJCMiQuo8) * [RuTube](https://rutube.ru/video/dd892631a12710bea4ef59c5dc40eeef/) __Расшифровка скринкаста__ (Пересказ от "Алиса AI") В разработке на __Vue.js__ (и вообще в фронтенде) важно чётко разделять два слоя: * __Бизнес‑логика__ — это «что мы делаем» с точки зрения продукта и требований. Это правила, которые определяют поведение системы: «пользователь может добавить товар в корзину», «если товар закончился, нельзя оформить заказ», «список фильмов должен быть отсортирован по рейтингу». * __Реализация__ — это «как мы это делаем»: конкретные технологии, библиотеки, HTTP‑запросы, маппинг данных, обработка ошибок, кэширование. Например: «запрос делаем через Axios», «данные храним в Pinia», «сортировку делаем через JS‑метод sort()». Разделение этих слоёв помогает писать поддерживаемый код и не смешивать требования бизнеса с техническими деталями. ### Почему это важно в Vue.js Во Vue легко «смешать» бизнес‑логику и реализацию прямо в компоненте: ```vue ``` Здесь в одном месте: * HTTP‑запрос (техническая деталь), * фильтрация по рейтингу (бизнес‑правило). __Проблемы такого подхода__: * Компонент становится «толстым» и сложным для тестирования: чтобы протестировать бизнес‑правило, придётся "мокать" HTTP‑запрос. "Мокать" (от английского mock - имитация) - термин из юнит-тестирования, обозначает подмену получения реальных данных (из БД или внешних API) во время тестирования. * При смене технологии (например, с __Axios__ на __fetch__) придётся менять и бизнес‑логику. * Нарушается принцип _единой ответственности_: компонент отвечает сразу за _отображение_, за _запрос_ и за _бизнес‑правила_. ### Практические способы разделения 1. Вынос бизнес‑логики в отдельные модули/сервисы Бизнес‑правила выносят в отдельный слой (сервис, composable, store), где нет привязки к конкретной реализации (подробнее разберем в следующих лекциях). А в компоненте остаётся только вызов: ```vue ``` Теперь компонент не знает, как именно загружаются фильмы — он просто запрашивает «топ‑фильмы». 1. Разделение на слои: API‑слой и бизнес‑слой Часто используют два уровня: * __API‑слой__ (только реализация): делает запросы, обрабатывает ошибки, маппит DTO → модель. * __Сервис/бизнес‑слой__: использует API‑слой, применяет бизнес‑правила, валидацию, логику состояний. Это позволяет менять реализацию (например, перейти с одного бэкенда на другой) без переделки бизнес‑правил. 3. Использование composables для переиспользуемой логики Во Vue __composables__ — удобный способ вынести логику из компонентов, но важно не превращать их в «сборную солянку». В composable лучше класть либо: * только бизнес‑правила (без знания про HTTP), * либо только реализацию (без бизнес‑правил). Тогда их легче тестировать и переиспользовать. Типичный пример: * Бизнес‑требование: «Корзина должна показывать итоговую сумму с учётом скидок и налогов». * Реализация: «Запрос к API корзины, парсинг JSON, округление до двух знаков, форматирование валюты». Если всё это написано в компоненте корзины, то при изменении правил скидок придётся лезть в компонент и править его. Если же логика расчёта суммы вынесена в отдельный сервис, компонент просто отображает результат, а правила живут отдельно. ### Типичные ошибки и как их избегать * __Смешивание в компонентах__. Решение: выносить логику в сервисы/composables. * __Бизнес‑правила «зашиты» в шаблоны__. Например, фильтрация или сортировка прямо в `v-for`. Решение: делать это в JS‑слое, а в шаблоне только отображать. * __Слишком «тонкие» сервисы__, которые просто пробрасывают вызовы API. Решение: в сервисах должна быть именно логика (валидация, агрегация, правила), а не просто прокси. ### Вывод В разделе описано, как в Vue.js‑проектах отделять требования бизнеса от технических деталей. Это нужно, чтобы код был понятным, тестируемым и легко изменяемым. На практике это реализуется через вынос бизнес‑логики в отдельные сервисы и чёткое разделение на API‑слой (реализация) и бизнес‑слой (правила). ## #9 Учимся учиться > 5 минут * [YouTube](https://www.youtube.com/watch?v=ekrzshM4AHI) * [RuTube](https://rutube.ru/video/100ab08808ebc706fe69ff9e8d9a132a/) ## #10 Криптономикон-1 - Vue.js: практика > 39 минут Ниже приведен вольный пересказ этого скринкаста с переписыванием под `Vue3 + script setup`. Т.е. сначала просмотрите видео, чтобы понять о чём идет речь, а потом по пересказу попробуйте реализовать пример. * [YouTube](https://www.youtube.com/watch?v=0MEpPU3rWCk) * [RuTube](https://rutube.ru/video/5a7fa691b1fae3c7fa0d0dbf47dbfbdd/) ### Материалы к заданию 1. Материалы к изучению: под роликом на ютубе куча ссылок, но в принципе там раздел "Основы" от [Синтаксиса шаблонов](https://v3.ru.vuejs.org/ru/guide/template-syntax.html) до "Работы с формами" 1. [API для получения ключа:](https://www.cryptocompare.com/) **Расшифровка скринкаста** (вольный пересказ своими словами) **Внимание**! Cегодня мы с вами __напишем очень и очень плохой код__ почему так и зачем мы это сделаем? Мы это сделаем потому что когда вас учат писать сразу хороший код, вас учат решать задачу одним способом. Рано или поздно вы сталкиваетесь c задачами, решения которые вы не знаете и оказываетесь ситуации когда не понимаете хорошее ваше решение или плохое. Мы с вами вначале напишем плохой, но к сожалению распространенный код и шаг за шагом, в рамках этой серии видео, будем его улучшать. У нас, как и в реальной жизни, будут появляться новые требования заказчика, мы будем находить какие-то баги сами уже у себя и сами героический фиксить и так далее. Таким образом, на выходе вы не только получите хороший код для решения этой задачи, но и понимание как глядя на код понять что он действительно плохой. >В рамках расшифровки скринкаста я сразу буду переписывать его на Vue3, используя `vite` + `script setup` ### Описание проекта Чем же мы с вами займемся? Мы с вами напишем небольшое приложение, которое позволяет добавлять в список отслеживания криптовалюты, используя **api** `cryptocompare.com`. Соответственно мы будем иметь возможность добавить криптовалютные пары "имя валюты - USD" в наблюдение и, когда мы выбираем конкретную валюту, у нас внизу появляется график отслеживания. ### Создание нового проекта, удаление лишего В домашнем задании [первой лекции](./web_01.md) вы должны были научится создавать приложене **Vue**. Откроем его и удаляем "рыбу": * нам не нужно содержимое директорий `src/assets` и `src/components` * в `App.vue` удаляем всё из скрипта и шаблона (стили вообще удаляем) ```html ``` ```js ``` * в `main.js` комментируем строчку с импортом `./main.css` Можем запустить проект командой `npm run dev` и посмотреть на пустое окно, убедившись заодно, что нет ошибок ### Добавление вёрстки и стилей В этом репозитории есть каталог с файлами html и css ([/articles/cryptonomicon](./cryptonomicon/)). Можно открыть в браузере файл `index.html`, чтобы понимать, как должен выглядеть готовый проект  1. Скопируйте содержимое тега `
` из файла `index.htm` в ваш шаблон (внутрь тега `` вместо комментария) После копирования шаблона проект должен выглядеть как-то так:  Как видите все подключилось но выглядит криво. Очевидно нам нужны стили. Как можно подключить `css`? В рамках скринкаста стили добавлены прямо в файл `App.vue`, но мы сделаем более правильно: скопируйте файл `app.css` в каталог `src/assets` и в файле `main.js` раскомментируйте и поправьте строчку с импортом файла стилей ```js import './assets/app.css' ``` Теперь всё выглядит "красиво"  ### Начинаем работу с App.vue Сегодня все наше внимание будет приковано к файлу `App.vue`. Итак, что нам надо? Будем двигаться сверху вниз, оживляя эту страницу. Первое что нам надо это научиться заполнять поле "Тикер" и, когда нажимается кнопка "добавить", реагировать на нажатие. Как мы помним, сильной стороной **Vue** является так называемое **двухстороннее связывание**, когда мы можем определить _что-то_ в данных java-скрипта и вывести это _что-то_ на экран. И когда _что-то_ на экране поменяется оно автоматически изменится в приложении. Ну что же давайте учиться это делать. Как вы помните **vue** декларативен. Что это означает? Это означает, что нам надо будет выучить язык описания компонентов, благо он не сложный. То есть у нас есть несколько заранее зарезервированных слов, с помощью которых мы будем объявлять те или иные особенности компонент. >Дальше в скринкасте расписывается функция `data()`, которая возвращает реактивные данные, доступные в шаблоне. Но это устаревший синтаксис __Option API__ из **Vue2**, во **Vue3** стандартом является `Setup API`, причем имеющий два варианта написания: функция `setup()` и ` ``` Задав ей значение по умолчанию (`'default'`) просто чтобы мы увидели как же осуществляется "двухстороннее связывание". Как вы помните, **vue** это **html-first** фреймворк, это означает что мы пишем html, а дальше с помощью специальных атрибутов и интерполяций подсказываем как связать наш html с данными и первый атрибут (все атрибуты которые используют **vue** начинаются c `v-`) это `v-model`. `v-model` как раз говорит "свяжи мне в две стороны вот этот вот __input__ с данными (переменной _ticker_)"   И вот у нас в поле ввода появилось значение `default`, но перед тем как что то делать я бы хотел убедиться что связь работает в обе стороны, т.е. когда правим поле ввода меняется и значение переменной. #### [Интерполяция](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation) Мы используем так называемый синтаксис интерполяции... это две фигурные скобки. Обратите внимание их можно использовать только в тех местах где вы вводите текст просто на странице. То есть я не могу его использовать где-то внутри атрибута, только там где просто обычный текст. Например: ```html ``` Теперь, если начать менять содержимое поля ввода __input__, то будет меняться и содержимое метки (__label__) Мы научились с вами связывать переменные в две стороны. Это работает c инпутами, чекбоксами, с радио батонами. Потом мы научимся писать наши собственные компоненты которые умеют работать с `v-model` Давайте что-нибудь с этим сделаем а что мы можем с этим сделать? Например при нажатии кнопки "добавить" я хочу чтобы что-то произошло. Как бы мы это делали в обычном java-скрипте? Мы нашли бы элемент на страничке через query-селектор, добавили слушатель на события клик и после этого сказали бы какую функцию вызывать. Во __VUE__ все работает похожим образом. Мы пишем `v-on:click="..."` (мы говорили что все атрибуты **VUE** начинаются с `v-`), дальше имя события (__click__). Мы здесь можем написать обычный java-скрипт код (например, `"ticker = 123"`). И при нажатии кнопку "добавить" в переменную `ticker` запишется значение `123` и верстка автоматически изменилась (поменялось содержимое поля ввода и метки). Но согласитесь писать код прямо в верстке как то странно, поэтому мы хотим чтобы код можно было писать рядом с вёрсткой (вспоминаем про **SFC**) >В оригинальном видео рассказывается про ключевое слово `method`, но это тоже устаревший синтаксис. Мы просто в ` ``` Обратите внимание! В обработчик события можно будет потом передавать аргументы, то есть в 99% случаях надпись `add` и `add()` абсолютно одинаковы. >Я поменял alert на вывод в лог, чтобы сразу показать как работать с инструментами разработчика в браузере > >Кликните правой кнопкой в окне браузера и выберите пункт "Просмотреть код" (есть короткая клавиша __F12__) > >Затем в закладках выберите "Консоль": > > Хорошо, но нам же хочется в скрипте дотянуться до значения, введенного в `input`. Как же нам это делать? >...`this` используется только во **Vue2**, во **Vue3** используется ЗНАЧЕНИЕ (поле `value`) реактивной переменной ```js function add () { consol.log(ticker.value) } ``` Проверяем, действительно вывелось ровно то значение которое введено в `input`. Подождите, я хочу ещё, чтобы это событие срабатывало, когда я нажимаю кнопку `Enter` при вводе названия тикера (дальше я пропустил полет мысли и привожу финальный результат: `v-on:keydown.enter` - при возникновении события нажатия клавиши `Enter` выполнить функцию `add`) ```js