This commit is contained in:
Vladislav Moiseev 2025-04-01 23:44:31 +04:00
parent de88d7f5c9
commit 27cb891083
4 changed files with 147 additions and 5 deletions

@ -20,7 +20,7 @@ Frontend:
- [Лабораторная работа №F1 - Макет одностраничного сайта (Figma)](./lwF1/README.md)
- [Лабораторная работа №F2 - Каркас одностраничного веб-приложения (React)](./lwF2/README.md)
- [Лабораторная работа №F3 - Стилизация веб-приложения (React)](#)
- [Лабораторная работа №F3 - Стилизация веб-приложения (React)](./lwF3/README.md)
- [Лабораторная работа №F4 - Взаимодействие с API (Axios)](#)
- [Лабораторная работа №F5 - Повторение на базовых технологиях (HTML, CSS)](#)

@ -2,7 +2,7 @@
## Цель работы
Освоение средств прототипирования веб-приложений.
- Освоение средств прототипирования веб-приложений.
## Ход выполнения работы

@ -2,9 +2,10 @@
## Цель работы
Освоение среды локальной фронтенд-разработки на базе NodeJS.
Освоение языка программирования TypeScript.
Освоение библиотеки для построения одностраничных приложений React.
- Освоение среды локальной фронтенд-разработки на базе NodeJS.
- Освоение языка программирования TypeScript.
- Освоение библиотеки для построения одностраничных приложений React.
- Освоение принципов декомпозиции одностраничных веб-приложений.
## Ход работы

141
lwF3/README.md Normal file

@ -0,0 +1,141 @@
# Лабораторная работа №F3 - Стилизация веб-приложения (React)
## Цель работы
- Освоение принципов стилизации элементов при помощи конструкций CSS.
- Освоение использования компонентов готовых дизайн-систем в React.
## Ход работы
1. Подключить к проекту дизайн-систему.
2. Для компонентов, которые в работе F2 разрабатывались вручную, найти аналоги.
3. Начать использовать компоненты из дизайн-системы.
4. Добавить собственные стили при помощи CSS-модулей, чтобы вёрстка сайта была похожа на макет из работы F1.
5. При необходимости добавить изображения и фон.
> Для любителей хардкора пункты 1-3 можно пропустить, и всё делать самому.
## Подключение дизайн-системы
В nodejs есть стандартный менеджер пакетов NPM.
По аналогии с NuGet в DotNet и Maven в Java.
Обычно подключение дизайн-системы, как и любых других библиотек, происходит через указанный выше NPM командой `npm install`.
Её необходимо запускать в той директории, где располагается файл `package.json`.
После успешной установки библиотеки (или "зависимости" для нашего приложения) изменятся файлы `package.json` и `package-lock.json`.
В этих файлах описывается базовая информация о проекте и закрепление конкретных зависимостей сответственно.
> Что за закрепление зависимостей?
> Всё дело в том, что в `package.json` обычно указаны диапазоны зависимостей (например, `"zustand": "^4.5.5"`, то есть "любая версия от 4.5.5 строго до 5.0.0").
> В `package-lock.json` указывается конкретная версия, которая должна удовлетворять требованиям и быть использована при работе нашего приложения.
Пример команды подключения consta design:
```bash
npm install @consta/uikit @consta/icons @consta/header
```
Это команда установит компоненты из Consta UI и Consta Header, а также иконки из Consta Icons.
## Собственная стилизация через CSS-модули
В классическом документе HTML с подключёнными CSS все стили для всех элементов описываются глобально, а элементы, для которых и нужно определить какие-то стили, выбираются через "селекторы".
Пример селектора:
- `.text-danger` - все элементы, у которых определён аттрибут `class="<...> text-danger <...>"`, то есть хотя бы один класс - это `text-danger`;
- `.text.text-danger` - все элементы, у которых определены сразу два класса: и `text`, и `text-danger`;
- `p,h1` - этот селектор выбирает все абзацы (`<p>это абзац</p>`) и все заголовки первого уровня (если что, их 6 уровней);
- `a:hover` - для ссылок (`<a href="https://ulstu.ru/">Политех!</a>`), на которые пользователь навёл мышь.
Затем для каждого селектора объявляется набор правил стилизации, например:
```css
.text {
font-size: 16px; /* Размер шрифта */
}
.text.text-danger {
color: #ff0000; /* Красный цвет текста */
background-color: #ff9999; /* Розовый - цвет фона */
}
h1 {
border: 1px solid black; /* Стиль границ элемента */
border-radius: 10px; /* Радиус скругления границ */
}
```
Этот подход существует уже как несколько десятков лет, но есть нюанс.
Если сайт (веб-приложение, система) очень сложная и некоторые стили ещё и подключаются снаружи (например, та же дизайн-система), то можно легко схлопотать конфликт стилей.
Представим, что для примера выше где-то другой разработчик определил следующее:
```css
.text {
font-size: 14pt;
}
```
И что получится?
Размер шрифта должен быть `16px` или `14pt`?
Чтобы частично решить эту проблему, было предложено множество подходов.
Один из них: БЭМ (Блок, Элемент, Модификатор).
Он описывает правила, как должны называться классы, чтобы не было конфликта стилей, как выше.
Другой подход - использование модулей CSS.
При этом подходе для каждого компонента создаётся отдельный файл `%component_name%.module.css`, где можно указывать стили для конкретных элементов компонента.
Импортируется такой набор стилей как `import styles from './%component_name%.module.css'`, далее можно обращаться к переменной `styles`. Это - объект, в котором каждое поле - это название класса из CSS-модуля.
Предположим CSS-модуль для карточки (`Card.module.css`) описан таким образом:
```css
.header { /* Стили заголовка */ }
.text { /* Стили текста. Да, тут нет комментариев // */ }
.footer { /* Стили подвала */ }
```
Тогда если импортировать этот модуль в `Card.tsx` как `import styles from './Card.module.css'`, то в объекте `styles` будут следующие строки:
- `styles.header` - для `className`, связанного с заголовком;
- `styles.text` - для `className`, связанного с основным текстом;
- `styles.footer` - для `className`, связанного с подвалом.
Пример описания компонента `Card.tsx` может быть таким:
```tsx
import { ReactNode, PropsWithChildren } from 'react';
import styles from './Card.module.css';
interface Props {
header: string;
footer: ReactNode;
}
export const Card = (props: PropsWithChildren<Props>) => (
<div>
<h3 className={styles.header}>{props.header}</h3>
<div className={styles.body}>{props.children}<div>
<footer className={styles.footer}>{props.footer}</footer>
</div>
);
```
Вся мощь CSS-модулей - это уникальные названия селекторов.
Предположим, есть 2 CSS-модуля, и в обоих определён селектор `.header`.
Тогда при компиляции нашего приложения для одного из компонентов итоговое название класса, которое "увидит" браузер, может быть `_header_mdccx_73`, а для другого - `_header_mdccx_78`.
## Добавление изображений
Как добавлять статические файлы (к которым относятся документы, картинки, и т.д.) для vite [описаны в этой документации](https://vite.dev/guide/assets).
Если кратко, есть несколько путей:
- Скопировать файлы с изображениями в папку `public` и использовать в качестве ссылки на фон или изображение просто имя файла, например, `<img src="img.png" alt="" />`.
- Скопировать файлы с изображениями рядом с компонентом и импортировать их как `import imgBg from './img.png'`.
Тогда в переменную `imgBg` будет помещён сгенерированный url, который надо использовать по назначению, например, `<img src={imgBg} alt="" />`.
- Скопировать файлы с изображениями рядом с CSS-модулем и использовать значение свойства по типу `url('./img.png')`.
Например, `.text{ background: url('./bg.png'); }`.