Концепция компонентов фреймворка Vue [1] — основополагающая идея о том, что пользовательский интерфейс (UI) можно представить в виде дерева небольших, переиспользуемых, самостоятельных блоков, каждый из которых отвечает за свою часть логики и отображения.
Вместо одного огромного файла вы создаёте приложение из компонентов, как собираете сложную структуру из LEGO. Основная модель компонента — это однофайловый компонент (`.vue` файл), который инкапсулирует три части: шаблон (HTML), логику (JavaScript/TypeScript) и стили (CSS). Некую аналогию компонента можно произвести с классом языка C++ или модулем/структурой языка C, в которую встроены переменные и указатели на функции.
[Ключевые принципы компонентов Vue]
Принцип
Суть и пример
Инкапсуляция
Компонент объединяет связанные HTML, JS и CSS в одном файле (`.vue`). Внешнему миру доступен только его публичный интерфейс (props и события), а внутренняя реализация скрыта.
Переиспользование
Один раз созданный компонент (например, кнопка < BaseButton>, карточка < ProductCard>) можно использовать многократно в разных частях приложения с разными данными.
Иерархия и композиция
Приложение — это дерево компонентов. Сложные компоненты создаются путём вложений более простых (композиция). Например, < App> содержит < Header>, который содержит < NavMenu>.
Односторонний поток данных
Данные передаются сверху вниз от родительских компонентов к дочерним через props (входные параметры). Это делает поток данных предсказуемым.
Коммуникация через события
Дочерние компоненты общаются с родителями, отправляя пользовательские события ($emit). Родитель может на них реагировать.
Реактивность
Когда данные компонента меняются, Vue автоматически и эффективно обновляет связанные с ними части DOM. Разработчик управляет состоянием, а фреймворк заботится о его синхронизации с представлением.
Жизненный цикл
Каждый компонент проходит этапы: создание (инициализация), монтирование в DOM, обновление и удаление. На каждом этапе можно выполнять свой код с помощью хуков жизненного цикла (onMounted, onUnmounted и др.).
[Анатомия однофайлового компонента (SFC - Single File Component)]
Концепция компонентов — это сердце Vue. Она превращает разработку интерфейса из написания скриптов в проектирование системы взаимодействующих, переиспользуемых блоков. Именно эта концепция позволяет Vue-приложениям оставаться поддерживаемыми и масштабируемыми.
[Создание компонентов приложения Vue]
Общепринятая концепция - держать помещать каждый компонент в отдельную директорию components, которая находится в папке src. Далее показан пошаговый пример создания компонента для кнопки.
1. Создайте в папке src папку components.
2. В папке components создайте файл Button.vue. В этом файле создайте 3 пустые секции:
Такой единый шаблон применяется для всех компонентов, в том числе и для компонента самого приложения App. Однако файл приложения компонента App.vue находится в непосредственно в папке src.
scoped в теге < style scoped> компонентов Vue используется для ограничения области действия CSS-стилей только текущим компонентом. Если убрать scoped, то стиль для компонента станет глобальным, и применится ко всему проекту.
Как это работает:
1. Изоляция стилей - с использованием scoped стили применяются только к элементам текущего компонента.
- Предотвращение конфликтов стилей между компонентами - Автоматическая изоляция без именования классов вручную - Более чистая разработка - можно использовать простые имена классов
Ограничения:
Глубокие селекторы - для стилизации дочерних компонентов нужно использовать `::v-deep`, `:deep()` или `>>>`:
:deep(.child-class){ color:red;
}
Глобальные стили - если нужны глобальные стили, используйте < style> без scoped, или отдельный CSS-файл.
Когда использовать scoped:
- Компоненты многократного использования - для предотвращения стилевых конфликтов. - Библиотеки компонентов - для обеспечения изоляции. - Большие приложения - для поддержания порядка в стилях.
Когда не использовать:
- Глобальные стили (reset.css, переменные CSS). - Стилизация корневого элемента приложения. - Когда нужен доступ к стилям извне компонента.
scoped - один из ключевых инструментов Vue для создания поддерживаемых и изолированных компонентов.
3. В определении стиля можно использовать переменные из корневого файла style.css с помощью var. Например, в файле style.css есть определение градиента --gradient:
color: var(--primary); - цвет текста через CSS-переменную --primary
cursor: pointer; - меняет курсор на "руку" при наведении
Состояние при наведении .button:hover:
background: var(--gradient-inverted); - меняет градиент при наведении (инвертированный вариант, описанный в CSS-переменной --gradient-inverted)
Ключевые особенности:
Использование CSS-переменных (Custom Properties):
--gradient, --gradient-inverted - градиенты для разных состояний --font - шрифтовая гарнитура --primary - основной цвет текста
Это говорит о том, что тема компонента настраивается через глобальные CSS-переменные, что позволяет:
- Легко менять тему всего приложения - Создать согласованный дизайн-систему - Настраивать кнопку извне компонента (несмотря на scoped)
Визуальные характеристики кнопки:
Интерактивная - меняет фон при наведении Безрамная с закруглениями - современный плоский дизайн Крупная (padding 14px + font-size 20px) Выделенная (полужирный шрифт 600) Доступная (курсор pointer указывает на кликабельность)
Что означает scoped в этом контексте: стили применятся ТОЛЬКО к элементам с классом .button внутри этого конкретного компонента, даже если в других компонентах есть элементы с таким же классом.
С помощью тега < slot>< /slot> в компоненте можно передавать содержимое из компонента-родителя (обычно это компонент приложения App.vue) в дочерний компонент. Пример для дочернего компонента нашей кнопки показан ниже. Файл App.vue:
Тег < slot> в этом примере выполняет критически важную функцию — это система content projection Vue, аналогичная `children` в React или transclusion в Angular. В результате содержимое из < MyButton>< /MyButton> будет перенесено на компонент кнопки (в этом примере текст "Сохранить").
Замечание: тег < slot>< /slot> можно заменить на самозакрывающийся < slot />, что дает то же самое.
В компоненте можно применить несколько slot, используемых для разных целей. Для этого в slot вставляется атрибут name. Например для компонента Button.vue:
В этом примере определено 2 слота (оба самозакрывающиеся), один с именем icon, а второй безымянный. Можно определить произвольное количество именованных слотов с уникальными именами. Имя слота (в данном примере "icon") произвольное, и оно используется для ссылки на этот слот в родительском компоненте.
Слот, который не имеет имени называется слотом по умолчанию, все что будет положено в дочерний компонент, попадет в этот слот.
В родительском компоненте несколько слотов используются с помощью вложенных тегов template и директивы v-slot, например: